Re: Question on select() and sockets
- From: K-mart Cashier <cdalten@xxxxxxxxx>
- Date: Fri, 6 Jun 2008 22:04:03 -0700 (PDT)
On Jun 6, 8:10 pm, William Ahern <will...@xxxxxxxxxxxxxxxxxxxxxxxxx>
wrote:
K-mart Cashier <cdal...@xxxxxxxxx> wrote:
On Jun 6, 2:07?pm, Alex Fraser <m...@xxxxxxxxxxx> wrote:
K-mart Cashier wrote:
Why do sockets have to be 'non-blocking' when using select() to set
the timeout? Ie, why can't they be blocked?
You can use blocking calls to send()/recv()/read()/write() if you don't
care if you block in them - but I don't think that should ever be the
case if you are using select().
Making the sockets non-blocking guarantees control over when you block
(ie, in select()). Although I was writing about pipes in my recent reply
to Edd, the same applies to sockets (first block of my reply):
http://groups.google.co.uk/group/comp.unix.programmer/msg/b589bcb9068....
Alex
Perhaps I'm not thinking this through, but how
"This all sounds fine. But you must set the pipes non-blocking else
you
can still end up blocking, even if you only call read() or write()
after
select() says the descriptor is, respectively, readable or writeable:
Is this possible?
For pipes the scenario would probably involve another process or thread
invalidating the condition. For sockets there are many more potential
scenarios. A common one that I've personally experienced involves UDP
sockets on Linux. IIRC, what happens is that a UDP packet arrives from the
network and the UDP stack wakes-up/notifies any processes which registered
interest. A process calls recv/read/recvmsg, which tries to copy the packet
data to the user buffer, except the checksum verification was delayed,
occuring simultaneous with the copy. The checksum fails, the copy is
aborted, and the packet discarded. If the socket doesn't have the O_NONBLOCK
flag set, the system call never returns, and instead blocks the thread while
waiting for more data.
I imagine that scenarios involving fragmentation or IPSec abound.
This might all seem odd, but in fact it's but one more example of a common
phenomenon:
http://en.wikipedia.org/wiki/Time-of-check-to-time-of-use
In general, it's never a good idea to assume that a condition holds across
multiple system calls. You can enforce certain contracts within your own
application, but don't expect the kernel to be so chummy.
The lesson is apropos in your own code. One incredibly common exploit is
what often results when an application has two bodies of code: validating
code and operating code (i.e. check and use). The latest such exploit was
none other than the recent Flash VM code injection. When you have two bodies
of code which operate on the same data and _attempt_ to manifest the same
policies, its common that one body of code eventually drifts away (or,
perhaps more likely, was never perfectly synchronized). The result is that,
given the same data, they behave differently. The lesson is that, unless
you're invoking a discrete operation, don't assume a discrete result.- Hide quoted text -
- Show quoted text -
Okay, I need a day for that response to sink in.
.
- References:
- Question on select() and sockets
- From: K-mart Cashier
- Re: Question on select() and sockets
- From: Alex Fraser
- Re: Question on select() and sockets
- From: K-mart Cashier
- Re: Question on select() and sockets
- From: William Ahern
- Question on select() and sockets
- Prev by Date: Re: Question on select() and sockets
- Next by Date: Re: Streams files
- Previous by thread: Re: Question on select() and sockets
- Next by thread: Re: Question on select() and sockets
- Index(es):
Relevant Pages
|