Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!cornell!uw-beaver!rice!sun-spots-request From: ultra!beau@ames.arc.nasa.gov (Beau James) Newsgroups: comp.sys.sun Subject: Re: LWP experience -- comments on "select()" Keywords: Windows Message-ID: <162@brazos.Rice.edu> Date: 5 Jul 89 18:15:25 GMT Sender: root@rice.edu Organization: Sun-Spots Lines: 61 Approved: Sun-Spots@rice.edu X-Sun-Spots-Digest: Volume 8, Issue 73, message 2 of 19 In SunSpots v8n60, Mike Schwartz writes (regarding select() and LWPs): --> When the I/O is complete, the UNIX process gets a SIGIO, and the LWP --> package must decide which thread(s) to awaken. But as it is currently --> implemented, every thread that is waiting on SIGIO gets reawakened. --> The result is that the semantics of select are not correctly --> implemented -- a thread could return from select with no I/O available, --> and before the timeout has expired. This breaks existing applications --> that you are trying to convert to use LWPs (as I was doing in one --> case). If the goal is to have an application that will not pend on an I/O operation, then the applications were "broken" anyway. The only way to eliminate the possibility of waiting on I/O is to use non-blocking I/O, and be prepared to handle an EWOULDBLOCK, even when using select(). A simple select() construct looks something like: select(data available to read?); read(); To never block on I/O, the select() outline should be: for(;;) { select(data available to read?); if (read() > 0) break; else if (errno == EWOULDBLOCK) continue; else abort(); } Otherwise, there is a timing window. The window looks to be only one line of code wide in the user process: small, but still an open window. And in reality, the window is wider. When the kernel processes the select() call, and the selected-for condition is true, the user process is simply scheduled to resume. By the time the user process actually runs, lots of other kernel activity and possibly lots of other user processes may have run. The selected condition may have changed before the user process has a chance to take action, even for files/devices being used exclusively by one process. Example: a tty input buffer may get flushed by the kernel under certain overflow conditions. So data may have been readable at the time of select(), but not be there at the read(). In a situation where several processes are sharing the same file/device, it's quite likely that the select() condition will change out from under some of the. The semantics of select() are to wake up all the processes awaiting the same condition, so the first one that runs may change the condition (e.g. read all the available data, or fill the output buffer) before the second gets a chance. It WOULD be a bit more efficient if the LWP library only woke up "interested" threads. But there may be more than one thread selecting on the same fd/condition - so the application code still has to deal with the situation as above. Beau