Atomicity of select for read followed by read
Peter Dufault
dufault at hda.com
Tue Sep 14 12:17:53 UTC 2010
This is not RTEMS specific.
Does anyone want to venture some thoughts on the atomicity of the following sequence in the specific case of a pool of threads of identical fixed priority running under a fixed-priority scheduler?
The sequence is:
/* If valid_socket is set to a blocking socket can
* select ever return ready and yet the read still block?
*
* All readers are the same priority threads running under
* the fixed-priority scheduler.
*/
ssize_t is_this_atomic(int valid_socket,
struct timeval *tmo)
{
ssize_t ready;
fd_set readfds;
char byte;
FD_ZERO(&readfds);
FD_SET(valid_socket, &readfds);
ready = valid_socket + 1;
if ((ready = select(ready, &readfds, 0, 0, tmo)) > 0) {
return read(valid_socket, &byte, 1); /* XXX Will this ever block? XXX */
}
return ready;
}
Say there is a pool of threads, all running at the same priority, all running under the fixed-priority scheduler, reading from a single socket opened to a remote serving device.
For the read to block what I think this has to happen:
T1: Select says data is available, T1 goes to read it, but...
A different thread, T2, is activated as a result of calling the read. It can't be an asynchronous event that activates T2 since T1 and T2 are of the same priority, and so if activated T2 should go in line behind T1. Maybe there is more data available, I don't think that is relevant to the discussion.
T2: Select says data is available, and it reads all available data, and blocks.
T1: ...Resumes and goes to read, but no data is available, and it blocks with no timeout and hangs.
The question boils down to what the restrictions are on the implementor of select() and read() (e.g., RTEMS). Obviously if calling read() requires getting a resource that T2 has then T1 could block and T2 could run, but that is a restriction on the implementation of select() and read().
There are case-by-case solutions to this, e.g. a mutex around select and read, but I'm dealing with a situation where a variation on this idiom occurs frequently.
I don't know what RTEMS does, RTEMS is the server where I'm seeing this problem.
My opinion is this should be guaranteed, but that's just my opinion.
PS: In one Linux man page I found this under BUGS. I'm interested in the definition of the behavior in the absence of bugs, though.
Under Linux, select() may report a socket file descriptor as "ready for
reading", while nevertheless a subsequent read blocks. This could for
example happen when data has arrived but upon examination has wrong
checksum and is discarded. There may be other circumstances in which a
file descriptor is spuriously reported as ready. Thus it may be safer
to use O_NONBLOCK on sockets that should not block.
Peter
-----------------
Peter Dufault
HD Associates, Inc. Software and System Engineering
More information about the users
mailing list