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 assert
will 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/urandom
will 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
/write
are 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
/write
do 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 readv
which guarantees strict atomicity (no mixing/intermingling, ever). Anything that goes in/out of readv
/writev
is processed as one atomic unit, always (except on pipes, when exceeding a size of PIPE_BUF
, as pointed out by rodrigo).
read is thread safe in the sense that it is a system call, and if you do multiple reads from multiple threads, each read will be processed serially. That is to say thread A will read M bytes, thread B will read the next M bytes, and so on, rather than thread A reading a few bytes, thread B reading a few bytes, then thread A reading more bytes.
The same is true of write.
The usual issue with multiple threads doing reads and writes is that often they read/write 1 character at a time, so there's a hack of a lot of opportunity to mix up where the input goes and the output comes from - and often the confusion is added to by language runtime libraries existing on top of read/write
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With