Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Socket that won't close

12 views
Skip to first unread message

Alex Taylor

unread,
May 17, 2009, 3:41:01 AM5/17/09
to
I'm writing a REXX program that runs a TCP/IP daemon thread using RXSOCK.

The socket is created as follows (error handling omitted):

socket = SockSocket('AF_INET', 'SOCK_STREAM', 0 )
CALL SockIoctl socket, 'FIONBIO', 1
rc = SockSetSockOpt( socket, 'SOL_SOCKET', 'SO_LINGER', '1 2')
address.!family = 'AF_INET'
address.!port = 2780
address.!addr = 'INADDR_ANY'
rc = SockBind( socket, 'address.!')
rc = SockListen( socket, 5 )

The daemon thread is then started, which basically runs a SockAccept() loop
until a quit event is posted, at which point it calls SockClose( socket )
and then signals the main program to exit.

This works fine about 80% of the time. Sometimes, however, I discover
once the program has exited that the socket is still open, stalled in
TIME_WAIT status. It usually stays that way for about 20 seconds or so,
during which time of course I can't restart the daemon successfully.

I've tried with SO_LINGER both enabled and disabled. It makes no apparent
difference.

How can I make sure this wretched socket gets closed when the program
does?

--
Alex Taylor
Fukushima, Japan
http://www.socis.ca/~ataylo00

Please take off hat when replying.

Marty

unread,
May 17, 2009, 12:46:35 AM5/17/09
to

Do you do anything to unblock the receiving thread before exiting? Or
is the thread killed "harshly" when the main thread exits?

--
[Reverse the parts of the e-mail address to reply.]

Alex Taylor

unread,
May 17, 2009, 4:23:01 AM5/17/09
to
On Sun, 17 May 2009 04:46:35 UTC, Marty <n...@comcast.martyamodeo> wrote:

> > The daemon thread is then started, which basically runs a SockAccept()
> > loop until a quit event is posted, at which point it calls SockClose(
> > socket ) and then signals the main program to exit.
> >
> > This works fine about 80% of the time. Sometimes, however, I discover
> > once the program has exited that the socket is still open, stalled in
> > TIME_WAIT status. It usually stays that way for about 20 seconds or so,
> > during which time of course I can't restart the daemon successfully.
>

> Do you do anything to unblock the receiving thread before exiting? Or
> is the thread killed "harshly" when the main thread exits?

As I say, on program exit, I post an event to the daemon thread which tells
it to break out of its loop. At that point, it calls SockClose, then posts
an event back to the main program tell it that it's safe to exit.

When the user goes to exit the program, I post this event to the daemon
thread:

IF listener.!thread > 0 THEN DO
rc = VRMethod('Application', 'PostQueue',,
listener.!thread, 0, 'finished = 1')
END

(I also post termination messages to any client socket threads that may be
active, but that part seems to be working as it should.)

The daemon thread's loop looks like this:

finished = 0
CALL VRInit
DO WHILE finished == 0
csock = SockAccept( socket )
IF csock > 0 THEN DO
CALL VRMethod 'Application', 'PostQueue', 0, 1,,
'CALL Event_Incoming', 'ClientSocket', csock
END
_VREEvent = VREvent('N')
INTERPRET _VREEvent
END
IF socket > 0 THEN DO
rc = SockClose( socket )
IF rc \= 0 THEN CALL SockPSock_ErrNo()
END
CALL VRMethod 'Application', 'PostQueue', 0, 1, 'CALL Quit'
CALL VRFini

At which point the "Quit" method in the main program simply destroys the
window and exits, as usual.

Paul Ratcliffe

unread,
May 17, 2009, 5:07:07 AM5/17/09
to
On 17 May 2009 02:41:01 -0500, Alex Taylor <mai...@reply.to.address> wrote:

> The daemon thread is then started, which basically runs a SockAccept() loop
> until a quit event is posted, at which point it calls SockClose( socket )
> and then signals the main program to exit.
>
> This works fine about 80% of the time. Sometimes, however, I discover
> once the program has exited that the socket is still open, stalled in
> TIME_WAIT status. It usually stays that way for about 20 seconds or so,
> during which time of course I can't restart the daemon successfully.
>
> I've tried with SO_LINGER both enabled and disabled. It makes no apparent
> difference.
>
> How can I make sure this wretched socket gets closed when the program
> does?

It's all very annoying. I've never got to the bottom of it. Have you
tried putting in a SockShutDown() to see if that helps?

Alex Taylor

unread,
May 17, 2009, 6:45:01 AM5/17/09
to
On Sun, 17 May 2009 09:07:07 UTC, Paul Ratcliffe
<ab...@orac12.clara34.co56.uk78> wrote:

> > How can I make sure this wretched socket gets closed when the program
> > does?
>
> It's all very annoying. I've never got to the bottom of it.

Ah, so it's not just me? Not sure if that's a relief or a worry. :)

Does it happen only with RXSOCK, or with sockets in general?


> Have you tried putting in a SockShutDown() to see if that helps?

Well, now I have. And no, it doesn't help. :(

Paul Ratcliffe

unread,
May 17, 2009, 7:27:05 AM5/17/09
to
On 17 May 2009 05:45:01 -0500, Alex Taylor <mai...@reply.to.address> wrote:

>> > How can I make sure this wretched socket gets closed when the program
>> > does?
>>
>> It's all very annoying. I've never got to the bottom of it.
>
> Ah, so it's not just me? Not sure if that's a relief or a worry. :)
>
> Does it happen only with RXSOCK, or with sockets in general?

In general I think.

>> Have you tried putting in a SockShutDown() to see if that helps?
>
> Well, now I have. And no, it doesn't help. :(

Oh well, worth a shot. I think you'll just have to learn to live with it.

Paul Ratcliffe

unread,
May 17, 2009, 9:20:08 AM5/17/09
to
On Sun, 17 May 2009 11:27:05 GMT, Paul Ratcliffe
<ab...@orac12.clara34.co56.uk78> wrote:

>>> > How can I make sure this wretched socket gets closed when the program
>>> > does?
>>>
>>> It's all very annoying. I've never got to the bottom of it.
>>
>> Ah, so it's not just me? Not sure if that's a relief or a worry. :)
>>
>> Does it happen only with RXSOCK, or with sockets in general?
>
> In general I think.
>
>>> Have you tried putting in a SockShutDown() to see if that helps?
>>
>> Well, now I have. And no, it doesn't help. :(
>
> Oh well, worth a shot. I think you'll just have to learn to live with it.

Actually, having pursued this a bit more, I find that my server only
fails to bind with an "Address in use" error if it had connected clients
at the time I closed it, despite disconnecting them properly.
If it had no clients it restarted fine every time.
"netstat -s" never showed any lingering sockets either way.

Subsequent to this, I added a SO_REUSEADDR setsocketopt() to the socket
before binding and it now works properly all the time.
I can't remember why I didn't do this before...

This is on a machine with a 16 bit TCP/IP stack though. Perhaps I should
try it on a 32 bit stack as well.

Marty

unread,
May 19, 2009, 9:19:14 AM5/19/09
to

Is there some chance that the main application can post its message to
terminate the thread, but not give up the rest of its timeslice and exit
before the thread gets the message? In C-land, I would have some kind
of DosWaitThread type of thing in there.

Alex Taylor

unread,
May 20, 2009, 1:08:01 AM5/20/09
to
On Tue, 19 May 2009 13:19:14 UTC, Marty <n...@comcast.martyamodeo> wrote:

> > As I say, on program exit, I post an event to the daemon thread which
> > tells it to break out of its loop. At that point, it calls SockClose,
> > then posts an event back to the main program tell it that it's safe to
> > exit.
>

> Is there some chance that the main application can post its message to
> terminate the thread, but not give up the rest of its timeslice and exit
> before the thread gets the message? In C-land, I would have some kind
> of DosWaitThread type of thing in there.

I don't see how. If the daemon thread is active, then the main program
can only quit once it receives the 'done' message from the listener.

But I have no way of knowing what the VX-REXX runtime is doing internally,
of course...

Alex Taylor

unread,
May 26, 2009, 7:17:02 AM5/26/09
to
On Sun, 17 May 2009 13:20:08 UTC, Paul Ratcliffe
<ab...@orac12.clara34.co56.uk78> wrote:

> Actually, having pursued this a bit more, I find that my server only
> fails to bind with an "Address in use" error if it had connected clients
> at the time I closed it, despite disconnecting them properly.
> If it had no clients it restarted fine every time.
> "netstat -s" never showed any lingering sockets either way.
>
> Subsequent to this, I added a SO_REUSEADDR setsocketopt() to the socket
> before binding and it now works properly all the time.
> I can't remember why I didn't do this before...
>
> This is on a machine with a 16 bit TCP/IP stack though. Perhaps I should
> try it on a 32 bit stack as well.

Well, so far it seems to work here (crossing fingers). MPTS WR08708
(eCS 2.0rc4).

Thanks for the hint!

0 new messages