KeyboardInterrupt catch does not shut down the socketserver

I

Igor Katson

I have problems in getting a SocketServer to shutdown. Why does this not
actually stop the application?

from SocketServer import UnixStreamServer, BaseRequestHandler

server = UnixStreamServer('/tmp/ss.sock', BaseRequestHandler)
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()


After that the server does not respond any more, but the application hangs.

What's the proper way to shutdown the socketserver and what is my mistake?
 
G

Gabriel Genellina

En Fri, 15 May 2009 09:04:05 -0300, Igor Katson escribió:
Shutdown implies closing the listening socket, doesn't it?

No (perhaps it should, but that is another issue). There is a
documentation bug; BaseServer.shutdown is documented as "Tells the
serve_forever() loop to stop and waits until it does." [1]
The docstring is much more explicit: """Stops the serve_forever loop.
Blocks until the loop has finished. This must be called while
serve_forever() is running in another thread, or it will deadlock."""

So, if you have a single-threaded server, *don't* use shutdown(). And, to
orderly close the listening socket, use server_close() instead. Your code
would become:

from SocketServer import TCPServer, BaseRequestHandler

server = TCPServer(('localhost',1234), BaseRequestHandler)
try:
server.serve_forever()
except KeyboardInterrupt:
print "^C detected"
pass
finally:
print "server_close()"
server.server_close()
print "bye"

(I've opened http://bugs.python.org/issue6031 )

[1]
http://docs.python.org/dev/library/...t=baseserver#SocketServer.BaseServer.shutdown
 
I

Igor Katson

Gabriel said:
En Fri, 15 May 2009 09:04:05 -0300, Igor Katson escribió:
Shutdown implies closing the listening socket, doesn't it?

No (perhaps it should, but that is another issue). There is a
documentation bug; BaseServer.shutdown is documented as "Tells the
serve_forever() loop to stop and waits until it does." [1]
The docstring is much more explicit: """Stops the serve_forever loop.
Blocks until the loop has finished. This must be called while
serve_forever() is running in another thread, or it will deadlock."""

So, if you have a single-threaded server, *don't* use shutdown(). And, to
orderly close the listening socket, use server_close() instead. Your code
would become:

from SocketServer import TCPServer, BaseRequestHandler

server = TCPServer(('localhost',1234), BaseRequestHandler)
try:
server.serve_forever()
except KeyboardInterrupt:
print "^C detected"
pass
finally:
print "server_close()"
server.server_close()
print "bye"

(I've opened http://bugs.python.org/issue6031 )

[1]
http://docs.python.org/dev/library/...t=baseserver#SocketServer.BaseServer.shutdown
Hmm. Gabriel, could you please show the same for the threaded version?
This one deadlocks:

from SocketServer import TCPServer, BaseRequestHandler
from threading import Thread

server = TCPServer(('localhost',1234), BaseRequestHandler)
try:
run_thread = Thread(target=server.serve_forever)
run_thread.start()
run_thread.join()
except KeyboardInterrupt:
print "^C detected"
pass
finally:
print "server_shutdown()"
kill_thread = Thread(target=server.shutdown)
kill_thread.start()
print "bye"
 
G

Gabriel Genellina

Gabriel said:
En Fri, 15 May 2009 09:04:05 -0300, Igor Katson escribió:
Lawrence D'Oliveiro wrote:
In message <[email protected]>, Igor
Katson wrote:
Lawrence D'Oliveiro wrote:
In message <[email protected]>,
Igor Katson wrote:

I have problems in getting a SocketServer to shutdown.
Shutdown implies closing the listening socket, doesn't it?

No (perhaps it should, but that is another issue). There is a
documentation bug; BaseServer.shutdown is documented as "Tells the
serve_forever() loop to stop and waits until it does." [1]
The docstring is much more explicit: """Stops the serve_forever loop.
Blocks until the loop has finished. This must be called while
serve_forever() is running in another thread, or it will deadlock."""

So, if you have a single-threaded server, *don't* use shutdown(). And,
to orderly close the listening socket, use server_close() instead. Your
Hmm. Gabriel, could you please show the same for the threaded version?
This one deadlocks:
[code removed]

The shutdown method should *only* be called while serve_forever is
running. If called after server_forever exited, shutdown() blocks forever.

<code>
from SocketServer import TCPServer, BaseRequestHandler
from threading import Thread

server = TCPServer(('localhost',1234), BaseRequestHandler)
run_thread = Thread(target=server.serve_forever)
run_thread.start()
try:
print "press ^C to exit"
import time; time.sleep(30)
except KeyboardInterrupt:
print "^C detected"
pass
server.shutdown()
run_thread.join()
print "bye"
</code>

But, what are you after, exactly? I think I'd use the above code only in a
GUI application with a background server.
There are other alternatives, like asyncore or Twisted.
 
I

Igor Katson

Gabriel said:
Gabriel said:
En Fri, 15 May 2009 09:04:05 -0300, Igor Katson escribió:
Lawrence D'Oliveiro wrote:
In message <[email protected]>,
Igor Katson wrote:
Lawrence D'Oliveiro wrote:
In message <[email protected]>,
Igor Katson wrote:

I have problems in getting a SocketServer to shutdown.
Shutdown implies closing the listening socket, doesn't it?

No (perhaps it should, but that is another issue). There is a
documentation bug; BaseServer.shutdown is documented as "Tells the
serve_forever() loop to stop and waits until it does." [1]
The docstring is much more explicit: """Stops the serve_forever loop.
Blocks until the loop has finished. This must be called while
serve_forever() is running in another thread, or it will deadlock."""

So, if you have a single-threaded server, *don't* use shutdown().
And, to orderly close the listening socket, use server_close()
instead. Your
Hmm. Gabriel, could you please show the same for the threaded
version? This one deadlocks:
[code removed]

The shutdown method should *only* be called while serve_forever is
running. If called after server_forever exited, shutdown() blocks
forever.

[code removed]
But, what are you after, exactly? I think I'd use the above code only
in a GUI application with a background server.
There are other alternatives, like asyncore or Twisted.
For now, I am just using server.server_close() and it works. The server
itself is an external transaction manager for PostgreSQL, when a client
connects to it, serialized data interchange beetween the server and the
client starts, e.g. first the client sends data, then the server sends
data, then again the client, then the server and so on.
I haven't used asyncore or Twisted yet, and didn't know about their
possible usage while writing the project. I'll research in that direction.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top