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