Hi Holger, On 26 Mar 2013, at 12:12, Holger Hans Peter Freyther <holger@freyther.de> wrote:
Hi,
I am porting a tooling class that I wrote on GST for my SIP and MGCP code to Pharo. This class will create a socket and then fork a RX and TX process. I have some issues with 'stopping' the socket. I have created an example that shows the issue in Pharo 2.0 and Pharo 1.4 with the pharovm (and to have more debug output with a re-compiled one).
| s rx | s := Socket newUDP. rx := [ [s waitForData. s halt] on: ConnectionClosed do: [ s halt] ] fork. "Wait for the process to hit the readSemaphore" (Delay forSeconds: 3) wait. s close.
My expectation is that I will get the ConnectionClosed signal or at least that >>#waitForData will return once the socket is closed. This is based on reading the comment of >>#waitForData.
The Socket>>#waitForData documentation reads like this: "Wait for data to arrive. This method will block until data is available or the socket is closed. If the socket is closed a ConnectionClosed exception will be signaled."
I had a look at the socket plugin and the following is happening. First aio is disabled, the state set to ThisEndClosed, then ::close is called and in the above case the result is '0' and the following code will be executed:
else if (0 == result) { /* close completed synchronously */ SOCKETSTATE(s)= Unconnected; FPRINTF((stderr, "closeConnection: disconnected\n")); SOCKET(s)= -1; }
this means that my 'rx' process will happily wait on the readSemaphore of the Socket and will never be woken up.
My question are probably:
1.) Is this the intended behavior for Socket>>#close and Socket>>#waitForData? 2.) How should I terminate my RX process?
kind regards holger
PS: The issue is probably socket specific and not related to UDP.
Maybe I am telling you things you already know, but TCP and UDP are fundamentally different. UDP is really one-shot, try-and-hope, completely asynchronous. In networking you generally only get a ConnectionClosed when you actually read or write (and even then ;-). The Socket API has many strange methods, most of which you should not touch. You should use SocketStream. Looking in the VM code is also misleading because the 3 platforms (Mac, Win, *nix) are different. In Socket[Stream] there is lots of historic baggage. I would suggest you look at Smalltalk code that actually works (for TCP, Zinc Client and Server code would do, for UDP, ZTimestampSNTPClient for example). For your concrete question (2): just start a reading process, wrap it in a handler and clean up. For UDP this will never happen: you will keep on reading nothing. For TCP reading will eventually fail if the other end disappears. HTH, Sven -- Sven Van Caekenberghe http://stfx.eu Smalltalk is the Red Pill