> Lett Bjarke Bruun <bbj / swooplinux.org>
> Aihe: Re: TCPSocket hangs after ctrl-c
> 
> On Sunday 16 January 2005 15:27, ts wrote:
> > >>>>> "B" == Bjarke Bruun <bbj / swooplinux.org> writes:
> >
> > 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, 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

You do want to stop the program from the CLI but using a SIGTERM or 
a SIGHUP rather than forcing a quit, right? I'd say it would be the
cleanest to trap the signal from your main process and then make sure
the child gets killed, too. Signal#trap and Process#abort should work
for that unless you want to set up a pipe/signal and bring the child 
down more gracefully (in the event there's a read in progress).

Are you having problems with the SERVER QUIT command?

E