[Python-Dev] Re: Integrating timeoutsocket.py

Michael Gilfix mgilfix@eecs.tufts.edu
Sat, 27 Apr 2002 19:15:08 -0400


  Gonna carbon the dev list to get people's opinions on this
one. Something definitely needs to change in the way ServerSocket.py
is implemented.

  Found the cause in ServerSocket.py. You need to add the line:

    t.setDaemon (1)

  at line 469 in ServerSocket.py, right after the thread is
created. Whether this is an error is debatable though. The problem
is that the other threads don't know you're exiting, so they
continue running after you exit. Ideally, we should either just set
the client threads as daemon threads or we should have some way of
signaling them that they must terminate. One solution without touching
ServerSocket is to subclass off of ThreadingMixIn and create a new
ThreadingTCPServer class.  Not too elegant though.

  The docs for the thread module say:

"Threads interact strangely with interrupts: the KeyboardInterrupt
exception will be received by an arbitrary thread. (When the signal
module is available, interrupts always go to the main thread.)"

  Kinda unfortunate in this scenario.

                    -- Mike

On Sat, Apr 27 @ 12:44, Bernard Yue wrote:
> About the test.  I am facing this problem with Threading server (using
> SocketServer module).  
> The new socket module somehow change the behavior of the threading
> server.  The change happens during server exit.
> 
> With the old module, when there is are client(s) connected to the
> server, existing the server by KeyboardInterrupt will close the
> connection with all the connecting client.  Not the case for the new
> module.  The thread which serving a connected client will stays on until
> the client exit.
> 
> I am not exactly sure why it happens.  Attached is the script, use
> telnet client to do the test and see if you can figure out why.
> 
> 
> 
> Bernie
> ===================================================================
>
#!/usr/bin/env python
'#!/home/bernie/src/python23/dist/src/python'

import time
import select
import SocketServer


class RequestHandler( SocketServer.StreamRequestHandler):
    def __init__(self, request, client_address, server):
        SocketServer.StreamRequestHandler.__init__(self, 
                request, client_address, server)
        
    def handle( self):
        """Handle a client"""
        _remote_id = '%s:%s' % self.request.getpeername()
        print 'Client %s connected' % _remote_id
        self.wfile.write( 'Hello %s\n' % _remote_id)

        while 1:
            select.select( [self.rfile.fileno()], [], [])
            try:
                _in = self.rfile.readline()
                if not self.process_command( _in, _remote_id):
                    break
            except IOError:
                break    # connection reset by requester

        print '%s quited' % _remote_id

    def process_command( self, command, client='anonymous'):
        _command = command.strip()
        if _command == 'exit' or not command:
            return 0

        if _command:
            print 'Request from %s: [%s]' % (client, _command)
            self.wfile.write( 'Command [%s] received!\n' % _command)
            self.wfile.flush()

        return 1


class MyTCPServer( SocketServer.TCPServer):
    def __init__( self, server_address, RequestHandlerClass, timeout=None):
        self.__timeout = timeout
        SocketServer.TCPServer.__init__( self, server_address, 
                RequestHandlerClass)

        '''
        # set timeout
        if self.__timeout:
            try:
                print 'Set timeout to %s second(s)' % self.socket.gettimeout()
                print 'Current time is %s' % time.asctime()
                self.socket.settimeout( self.__timeout)
            except AttributeError:
                print 'No timeout with socket'
        '''


class ThreadingTCPServer( SocketServer.ThreadingMixIn, MyTCPServer): pass

def main( argv):
    if len(argv) == 1:
        print 'Usage server.py <IP address> <port>'
        return 0

    _address = ( argv[1], int(argv[2]))
    _server = ThreadingTCPServer( _address, RequestHandler, 3)

    try:
        _server.serve_forever()
    except KeyboardInterrupt:
        _server.server_close()
        print "Server Terminated!"
        

if __name__ == "__main__":
    import sys
    main( sys.argv)

-- 
Michael Gilfix
mgilfix@eecs.tufts.edu

For my gpg public key:
http://www.eecs.tufts.edu/~mgilfix/contact.html