Detecting a socket dropping in multi-threaded app


(Firestone, Mark - Technical Support) #1

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

def getstr(echo,wrapon,width) # Input a line a character
at a time.

whole = ""
fred = ""
i = 0
wlen = 0
suppress = false #This is to prevent
telnet control codes from being treated as user input

if @wrap != nil					#taking the length

of a nil is bad. we must test for this or BOOM!
whole = @wrap
i = whole.length
end

@wrap = ‘’
@socket.write whole

@socket.each_byte do  | fred| 
   
    case fred 
  when TELNETCMD
   suppress = true
   
      when  PRINTABLE 
   i = i + 1
   if !suppress then
    whole = whole + fred.chr 
        if echo then @socket.write fred.chr else @socket.write

NOECHOCHAR.chr end
end
if wrapon
if (i >= width) then
if fred != 32
wlen = 0
@wrap = whole.scan(/\w+/).last
wlen = @wrap.length if @wrap != nil
wlen.times { @socket.write BS.chr }
wlen.times { @socket.write " " }
@socket.write CR.chr+LF.chr
endbit = whole.length - wlen
#puts “endbit: #{endbit}”
#puts "whole: #{whole}"
whole.slice!(endbit…whole.length)
#puts "whole: #{whole}"
break
end
@socket.write CR.chr+LF.chr
break
end
end

      when CR 
       @socket.write CR.chr+LF.chr 
      break 
  
      when BS  
   if i >= 1 
        whole.chop!					#the user pressed

backspace, so get rid
i = i - 1
@socket.write fred.chr
end

      when DBS 
   if i >= 1 
        whole.chop!					#for UNIX based

Telnet
i = i - 1
@socket.write BS.chr
end #of if

    end		#of case

if fred < 250 then suppress = false 
  end

   end #of iterator

@socket.flush
getstr = whole
end

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.


#2

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.

···

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

Jonathan Gillette
iNetZ Media