TCPSocket hangs after ctrl-c

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

···

--
Bjarke Bruun
(Verify PGP-signature at hkp://pgp.mit.edu)
Vegetarians eat Vegetables, Humanitarians frighten me.

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

What class do you use for your server : TCPServer ?

Guy Decoux

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

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.

···

On Sunday 16 January 2005 15:27, ts wrote:

> 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 ?

----
# Author: Bjarke Bruun, bbj@swooplinux.org
# 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

--
Bjarke Bruun
(Verify PGP-signature at hkp://pgp.mit.edu)
Vegetarians eat Vegetables, Humanitarians frighten me.

      fork {

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

Guy Decoux

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 :slight_smile:

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?

···

On Sunday 16 January 2005 16:03, ts wrote:

> fork {

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

--
Bjarke Bruun
(Verify PGP-signature at hkp://pgp.mit.edu)
Vegetarians eat Vegetables, Humanitarians frighten me.

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 :-))

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

Guy Decoux

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

···

On Sunday 16 January 2005 16:29, ts wrote:

> 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, 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.

--
Bjarke Bruun
Vegetarians eat Vegetables, Humanitarians frighten me.

I know at this point, but I'll tackle one problem at a time (if you
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 :slight_smile:

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 :slight_smile:

···

On Sunday 16 January 2005 16:36, ts wrote:

> 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 :slight_smile:

Guy Decoux

--
Bjarke Bruun
Vegetarians eat Vegetables, Humanitarians frighten me.