Detecting a socket dropping in multi-threaded app


(Firestone, Mark - Technical Support) #1

Thanks for your reply. I had tried doing what you described, and it never
generates an exception. It just sits there.

If I set abort on exception = true, then the @socket.write command before
the interator generates an exception I can trap, just before the whole
program abends.

I tried testing for nils after the @socket.eachbyte, but that doesn’t work
either. I am not sure where to go from here… ideas? I don’t understand
your ping idea, as the client is a telnet session. Maybe I am being
thick…

Thanks,

Mark

From: why@rysa.inetz.com [SMTP:why@rysa.inetz.com]
Sent: 21 June 2002 18:48
To: ruby-talk@ruby-lang.org
Subject: Re: detecting a socket dropping in multi-threaded app

Firestone, Mark - Technical Support (mark.firestone@gossgraphic.co.uk)
wrote:

I’m still working on my Ruby BBS project. I need to be able to run some
code when a user drops offline without logging off. Right now, Ruby is
just
killing the thread. I need to know how to make it pass an exception (or
something) back to the main loop so the main loop can take the user out
of
the online user database. I’ve tried testing for nil and raising an
exception, but it doesn’t seem to work. Help please!! You guys never
let me
down.

thanks in advance!

Mark

First, I don’t see any begin…rescue around your TCPSocket#each_byte:

begin
@sock.each_byte do |fred|
# Process bytes sent
end
rescue
# Handle exception here…
end

I find the surest way of finding a disconnect is to implement a simple
PING request from the server to the client. It looks like your byte
commands could include a PING response from the client. I just run a
separate thread that periodically checks that the PING count is climbing…
Then, set Thread#abort_on_exception = false so you can make sure that only
clients that don’t return pings get killed. If you go this route, then
don’t forget to use a mutex.

Jonathan Gillette
iNetZ Media

NOTICE: This e-mail and any attachment(s) may contain confidential and
proprietary information of Goss International Corporation and/or its
subsidiaries and may be legally privileged. This e-mail is intended solely
for the addressee. If you are not the addressee, dissemination, copying or
other use of this e-mail or any of its content is strictly prohibited and
may be unlawful. If you are not the intended recipient please inform the
sender immediately and destroy the e-mail and any copies. All liability for
viruses is excluded to the fullest extent permitted by law. Any views
expressed in this message are those of the individual sender. No contract
may be construed by this e-mail.

···

-----Original Message-----


(Jonathan Gillette) #2

If I set abort on exception = true, then the @socket.write command before
the interator generates an exception I can trap, just before the whole
program abends.

Yep. You could wrap all socket read/writes in the begin…rescue block.

I tried testing for nils after the @socket.eachbyte, but that doesn’t work
either. I am not sure where to go from here… ideas? I don’t understand
your ping idea, as the client is a telnet session. Maybe I am being
thick…

Yeah, I forgot your client would be a simple telnet session. In the same vein as a ping, you could have a thread watching for inactive threads and shutting them down. So you could keep a timestamp on the last time a thread read a byte and shutdown the thread if too much time elapsed. In my Ruby socket servers, I tend to stay away from trying to catch all the possible exceptions and just keep a single thread that monitors the others. It’s just less of a headache. I guess I hate having to worry about missing an exception.

···

Firestone, Mark - Technical Support (mark.firestone@gossgraphic.co.uk) wrote:

Jonathan Gillette
iNetZ Media