TCPSocket hangs after ctrl-c

B

Bjarke Bruun

Hi there,

I'm new on the list and have tried google for help first, with no luck.

I'm writing a small tcpserver and when I debug it and make changes I
have to stop the server and I get a hanging socket

$ netstat -atn
<SNIP>
tcp 0 0 127.0.0.1:10000 127.0.0.1:44420
TIME_WAIT
</SNIP>

It hangs for apx. 30 secunds, not that I can't wait, but... when making
smalle incremeltal changes all the time in the debugging process it
becomes very tedious.

So, is there any way to send a proper kill signal to a runing ruby
script that will run an at_exit() function or the like so it'll shut
down cleanly?

Thanks
 
T

ts

B> I'm writing a small tcpserver and when I debug it and make changes I
B> have to stop the server and I get a hanging socket

What class do you use for your server : TCPServer ?


Guy Decoux
 
B

Bjarke Bruun

B> I'm writing a small tcpserver and when I debug it and make changes
I B> have to stop the server and I get a hanging socket

What class do you use for your server : TCPServer ?

It's a small smtp server - just for fun... need to learn somethings
about ruby and implementing rfc 821 seems well cool for starters :)

here is the core class (pre alpha everything you know :))

I've tried the "kill -9" and it seems to work, but I would like it to be
done in code not on the CLI.


----
# Author: Bjarke Bruun, (e-mail address removed)
# Copyright: GPL version 2

require 'socket'
require 'config'

# Process the commandline parameters
$cli = CliInfo.new # don't mind this - it's just for setting some
variables on the CLI.

class Server
def initialize
@data = nil
@f = File.new("rsmtp.log","a")
ss = TCPServer.new '0.0.0.0', 10000
server_going = true
going = true
while (@s = ss.accept) && server_going == true
@f.puts("S: -> Client session established <-\n")
fork {
@s.print "220 Ruby SMTP Server/#{$cli.val("version")} \r\n"

while going && @s.gets
if $_ == "SERVER QUIT"
# This is an attempt to send a "close" to the server so
# it'll shut down proberly.
server_going = false
@s.close
break
end
@f.puts("C: #{$_}")
sleep 1
r = cmd($_)
@s.print r
@f.puts("S: #{r}") if r != nil
if r =~ /^354(.*)/
r = getdata if r =~ /^354(.*)/
@s.print r
@f.puts("DEBUG > #{r}") if r != nil
end
if r =~ /^221(.*)/
@f.puts("S: -> Quitting sesion successfully <- \n\n")
@s.close
going = false
end
end
@s.close
}
end
@s.close
@f.close
end


def getdata
#puts "DEBUG: Receiving data"
@data = []
while @s.gets !~ /^\./
@data << $_
@f.puts("\t#{@data[-1]}")
end
"250 message accepted\r\n"
end

def cmd line
case line
when /^HELO \[\d*.\d*.\d*.\d*\]/
"250-#{$cli.val("SERVERNAME")} greets #{r}\r\n"
when /^EHLO \[\d*.\d*.\d*.\d*\]/
remote = line.split(/.\[/)
"250 #{$cli.val("SERVERNAME")} greets
#{remote[1].split("\]")}"#250-8BITMIME\r\n250-SIZE\r\n250-DSN\r\n250
HELP"
when /^MAIL FROM:(.*)/i
@sndr = $1
"250 OK\r\n" #: Sender okay\r\n"
when /^RCPT TO:(.*)/i
@rcpt = $1
"250: Recipient okay\r\n"
when /^DATA/i
"354 Enter data, end with newline and '.'\r\n"
when /^QUIT/i
"221 closing connection\r\n"
when /^RSET/i
"250 okay\r\n"
end
end

end

# Run the server with logging enabled (it's a separate thread).
server = Server.new
 
B

Bjarke Bruun

B> fork {

Why you don't use a thread, with a block local variable for @s

This is just a "test" for me. It's not (yet anyway) in progress of
beeing published... the rfc is large for startes, but the fork, IMHO,
has less footprint than threads and threads in ruby are only threads
inside the ruby process so the difference is the same until Matz et.
al. implements native threads for ruby (which I'm waiting for :))

The problem is not the local socket that is talking to the client it's
the main socket that hangs if I don't use "kill -9" and I would like to
find a way to fix that... "E S" has a point, but I'm new to Ruby and
don't quite know where to get info on usage of the
Signal#trap and Process#abort right now. Always glad to learn more but
from scratch is hard, if you remember :)

I'm looking for something like this

$ ./rsmtp.rb # the name of the server script

and then be able to press <ctrl-c> without having the socket hanging for
some 30 seconds before I can start the script again. I had a similar
experience in school a long time ago in C++ but I can't remember the
code I wrote back then to overcome this problem... and I don't have the
code anymore FYI.

I'm looking in "Programming Ruby: The Progmatic Programmer's Guide" with
no luck as to set up a trap for the script if it receives (SIG)KILL
signal - where to look?
 
T

ts

B> This is just a "test" for me. It's not (yet anyway) in progress of
B> beeing published... the rfc is large for startes, but the fork, IMHO,
B> has less footprint than threads and threads in ruby are only threads
B> inside the ruby process so the difference is the same until Matz et.
B> al. implements native threads for ruby (which I'm waiting for :))

Well, you do like you want but I hope that you have seen that you'll have
zombies.


Guy Decoux
 
B

Bjarke Bruun

B> This is just a "test" for me. It's not (yet anyway) in progress of
B> beeing published... the rfc is large for startes, but the fork,
IMHO, B> has less footprint than threads and threads in ruby are only
threads B> inside the ruby process so the difference is the same
until Matz et. B> al. implements native threads for ruby (which I'm
waiting for :))

Well, you do like you want but I hope that you have seen that you'll
have zombies.

I know at this point, but I'll tackle one problem at a time (if you
don't mind :))
 
T

ts

B> I know at this point, but I'll tackle one problem at a time (if you
B> don't mind :))

I can give you another problem : send a QUIT and the client will wait for
the connection be closed ...

Strange but I don't have all these problems with a thread :)

Guy Decoux
 
B

Bjarke Bruun

B> I know at this point, but I'll tackle one problem at a time (if
you B> don't mind :))

I can give you another problem : send a QUIT and the client will
wait for the connection be closed ...

Strange but I don't have all these problems with a thread :)

Guy Decoux


true, but now I've gotten the TIME_WAIT fixed with even though if the
server is killed the fork will hang for apx 30 seconds... but the
server will start again without problems.

the server is now started with

begin
server = Server.new
rescue SystemExit
server.close
end

where Server#close is

def close
@ss.close
end



So until next time you have my greatfull thanks - I love bright
minds/heads :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top