Subj : Re: Threading and Timeouts To : comp.programming.threads From : Giancarlo Niccolai Date : Wed Jul 20 2005 02:38 pm David Schwartz wrote: > > "Giancarlo Niccolai" wrote in message > news:dbl6j1$7qr$1@newsread.albacom.net... > >> Actually, I found that blocking i/o with select or poll works fine. Once >> select returns signaling that a socket can be read/written, a single >> read/write operation is GUARANTEED not to block; that's exactly what >> select >> is for. > > Nope, not true. The simplest example is if you 'write' more bytes than > there's buffer space for. A blocking socket will block until all bytes can > be queued. There are many other possible cases. > > DS From POSIX specification of the pselect/select function: """ If none of the selected descriptors are ready for the requested operation, the pselect() or select() function shall block until at least one of the requested operations becomes ready, until the timeout occurs, or until interrupted by a signal. """ And """ A descriptor shall be considered ready for reading when a call to an input function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully. (The function might return data, an end-of-file indication, or an error other than one indicating that it is blocked, and in each of these cases the descriptor shall be considered ready for reading.) A descriptor shall be considered ready for writing when a call to an output function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully. """ In other words, the standards GUARANTEES that if select()/pselect() declares a descriptor ready, it WILL NOT block the next read or write operation (depending on the type of request). OTOH, it does NOT GUARANTEES that all the data you may want to transfer is transferred; it does not even guarantees that ANY DATA AT ALL is transferred. In fact (always in the posix standard): """ If fildes refers to a socket, write() shall be equivalent to send() with no flags set. """ And from send: """ If space is not available at the sending socket to hold the message to be transmitted, and the socket file descriptor does not have O_NONBLOCK set, send() shall block until space is available [But note(1)]. If space is not available at the sending socket to hold the message to be transmitted, and the socket file descriptor does have O_NONBLOCK set, send () shall fail. [ this is the relevant portion] The select() and poll() functions can be used to determine when it is possible to send more data. """ Note(1): that is intended as "no space at all", that is, if it is currently impossible to send any meaningful portion of the data on the underlying protocol. After a call of select() which determines that the socket is READY for I/O, you are guaranteed to be able to send SOMETHING on the socket. If it's UDP, that means that there is enough space to send a datagram, if it's TCP that at least one byte can be sent without blocking. Actually, a write() on a socket will return the number of bytes actually transmitted, and NOT THE ONES YOU WISH TO TRANSMIT. So, your assertion "The simplest example is if you 'write' more bytes than there's buffer space for. A blocking socket will block until all bytes can be queued." is wrong, because if select determines that the socket is ready for write, the blocking socket WON'T BLOCK and will TRANSMIT IMMEDIATELY the portion of the data you requested to send that can be transmitted immediately. Consider also that (from send): """ .