Squeak Socket Primitives
Marcel Weiher
marcel at metaobject.com
Fri Nov 12 17:00:27 UTC 1999
> From: Craig Latta <Craig.Latta at NetJam.ORG>
[Andreas wrote]
> > "Client pushing data (using Correspondants prims)"
> > client _ NetStream tcpClientToPort: 22334 atHostNamed: 'localhost'.
> > client nextPutAll: (String new: 100000). "<- This will block!"
> >
> > ...and your Squeak stands forever.
> - My code only blocked because select() on win32 is broken (as
I found out during
> debugging). According to the Microsoft manual pages (and all
Berkeley sockets
> manual pages, and my own experience), select() on a blocking
socket is supposed
> to block until a desired operation (in this case, writing) is
possible without
> blocking. Instead, in this case (when the socket is an endpoint of
a virtual
> circuit from which a substantial amount of data has been written
without being
> consumed), it returns immediately, when the socket is not ready
for writing. My
> (blocking) write primitive is only called after this select()
returns. Since
> that return comes before the socket is ready for writing, it
blocks. I have a
> workaround if you truly think that example is compelling.
[..]
I am probably about to place my foot squarely into my mouth but here
it goes anyway:
select() only tells you that the descriptor is now ready to receive
*some* data. It doesn't specify how much. With a socket/pipe etc.
on UNIX it is usually one kernel buffer's worth ( typically 4K or
8K). That is the amount you should be able to safely write without
blocking. If you write more than a buffer's worth, your write() call
will *definitely* block, even if the receiver is picking up data
just fine, even in a pipe-situation, just to context-switch to the
other process and give it a chance to read.
So in the example above, the primitive should split any write into
4K chunks (or 1K just to be on the safe side) and then check before
each write. Of course, it could also just use non-blocking I/O.
> Anyway, it was true that at some point the client socket was
unable to send
> further data (no matter which primitives you use). The strange
thing was that my
> code blocked, since, as I've been trying to say, I designed my
framework to do any
> necessary waiting before actually attempting a blocking operation.
There
> seemed to be a bug somewhere.
See discussion above, this is to be expected, unless there is
something about your code that I do not understand.
BTW, this entire has been very interesting. I have a feeling that
it points to a need for a general solution for dealing with 'events'
from the outside world, essentially an abstraction that concentrates
event handling into a single place where these types of variables (
who is in charge, who blocks, etc. ).
Such an abstraction needs to be able to be used effortlessly by
implemenetations with minimal to no OS support (this is important
because they have the hardest task already), but should also not
stand in the way of integrating nicely with OSes that have rich
facilities in this area.
Marcel
(trying to extract foot from mouth...)
More information about the Squeak-dev
mailing list
|