Issue with threads and socket accept

V

Vasyl Smirnov

Hi,

I'm writing a multi-threaded server, and would like to stop it on a
signal (SIGINT on Ctrl-C in this case).
The problem is that after the first connection is accepted, and then
Ctrl-C is hit, the "while accept" loop doesn't break. If you hit Ctrl-
C before any connections, it just works fine. And the single-threaded
version, of course, works
as well.

Could somebody explain what am I doing wrong?

Below is a simple application that reproduces the problem. Change the
last line to "server.serve_seq" to run a single-threaded version.

Thanks in advance!


#!/usr/local/bin/ruby -w

require 'socket'

class MyServer
def initialize
@servsock = TCPServer.new("127.0.0.1", 1111)
end

def work(sock)
begin
lines = 0
lines += 1 while sock.gets
puts "Got #{lines} lines."
rescue Exception => e
print "exception: "; p e
ensure
sock.close
end
end

def serve_mt
while clisock = @servsock.accept
Thread.new(clisock) { |sock| work(sock) }
end
end

def serve_seq
while sock = @servsock.accept
work(sock)
end
end

def shutdown
return nil if @servsock.nil? or @servsock.closed?
puts "Shutting down..."
@servsock.close
end
end

server = MyServer.new
Signal.trap("INT") { server.shutdown }
server.serve_mt
 
C

Curt Sampson

I'm writing a multi-threaded server, and would like to stop it on a
signal (SIGINT on Ctrl-C in this case).
The problem is that after the first connection is accepted, and then
Ctrl-C is hit, the "while accept" loop doesn't break....
Could somebody explain what am I doing wrong?

Errr..."not investigating deep and strange mysteries of the Ruby interpreter
signal handling that are not comprehensible even after reading the source?"

I hope I get a point for that answer.

But anyway, much as I'd like to know *why* the signal handling is set up
to ignore signals when waiting in accept(), a situation on which the
source code that does this is particularly silent, I just live with the
solution, which is:

Do a select() before your accept(), and wait until the socket in
question becomes readable.

You and I are not the only ones caught by this, as it happens. The native
Ruby FastCGI code has the same issue.

cjs
 
F

Francis Cianfrocca

Note: parts of this message were removed by the gateway to make it a legal Usenet post.

Hi,

I'm writing a multi-threaded server, and would like to stop it on a
signal (SIGINT on Ctrl-C in this case).
The problem is that after the first connection is accepted, and then
Ctrl-C is hit, the "while accept" loop doesn't break. If you hit Ctrl-
C before any connections, it just works fine. And the single-threaded
version, of course, works
as well.

Could somebody explain what am I doing wrong?


Without addressing your specific question, let me suggest that you
investigate the Ruby/Eventmachine library. It should make your application
easier to develop.
 
V

Vasyl Smirnov

Without addressing your specific question, let me suggest that you
investigate the Ruby/Eventmachine library. It should make your application
easier to develop.

Thanks, Francis, I'm just reading the docs for your library!
 
V

Vasyl Smirnov

Errr..."not investigating deep and strange mysteries of the Ruby interpreter
signal handling that are not comprehensible even after reading the source?"

I hope I get a point for that answer.

You probably do :)
But anyway, much as I'd like to know *why* the signal handling is set up
to ignore signals when waiting in accept(), a situation on which the
source code that does this is particularly silent, I just live with the
solution, which is:

Well, actually the signal handler gets called, it calls shutdown,
outputs a message
to the stdout and closes the server socket. And the main thread is
still inside accept.
Do a select() before your accept(), and wait until the socket in
question becomes readable.

I've tried this, with the same success:

def serve_mt2
until @servsock.closed?
IO.select([@servsock])
clisock = @servsock.accept
Thread.new(clisock) { |sock| work(sock) }
end
end
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top