Is it safe to do this:
int fd;
void thread_main()
{
char buf[M];
ssize_t r = read(fd, buf, M);
assert(r == M);
...
}
int main()
{
fd = open("/dev/urandom", O_RDONLY);
for (int i = 0; i < N; i++)
start_thread(i);
for (int i = 0; i < N; i++)
join_thread(i);
}
That is: After open(2)ing "/dev/urandom" from the main thread, is it safe to read(2) from it unsynchronized from different thread contexts?
Under what circumstances will the assert fire? Will two threads ever get the same data? What could go wrong?
Your code is safe insofar as it will not crash. The
assertwill never trigger. No two threads will (should) ever get the same random data (it is highly unlikely but still possible that two threads get two “different” random sequences which are incidentially the same, so this cannot be 100% guaranteed)./dev/urandomwill never block or return fewer bytes than you try to read, however, if you read a large enough amount, it will eventually run out of entropy, so the quality of the random numbers will eventually degrade slightly. Usually, this is still just good enough, and it takes a whole while before that happens too, but it’s something to be aware of (most people don’t need to care, but it might not be acceptable, depending on what you do).read/writeare threadsafe (insofar as they won’t crash or corrupt data or leave descriptors in undefined states) and in this special case also should not intermingle/split up bytes between reads/writes to/from different processes. In general, however,read/writedo not guarantee this. They may intermingle data on concurrent reads/writes, on some devices.It should however not be a problem, since random bits are still random if you get some other random bits and someone else gets some (different) bits in between.
If you think it is a problem for you, use
readvwhich guarantees strict atomicity (no mixing/intermingling, ever). Anything that goes in/out ofreadv/writevis processed as one atomic unit, always (except on pipes, when exceeding a size ofPIPE_BUF, as pointed out by rodrigo).