Threaded server: what's wrong with this code?

Ahmed MOHAMED ALI ahmedmo at wanadoo.fr
Thu Dec 25 08:03:41 EST 2003


Hi,
Sorry for my bad english because i am French-speaking.
The problem is in JMSocketThread.handle .When this function terminates its
execution flow,the parameter "self.request"  is not longer valid.
So the thread work with an invalid socket.For this reason,you got  the 'Bad
file descriptor' error.
To correct the problem here's the modified code.

#---Modified JMHandler  class

class JMHandler (SocketServer.BaseRequestHandler):
     def handle (self):
         print 'Client connected...'
        threadEvent = Event()  # create an event to wait for the thread
         JMSocketThread(self.request,threadEvent ).start() #  don't forget
to pass the event parameter here
         print 'Request handed off to a thread.'
        threadEvent.wait()

#---Modified JMSocketThread class

 class JMSocketThread (threading.Thread):
     def __init__ (self, theSocket):

threading.Thread.__init__(self,target=self._myRun,args=[theSocket,theEvent])
# don't forget to pass the event here
     def _myRun (self,theSocket,theEvent): #don't forget to pass the event
here too
         global THREAD_COUNT
         THREAD_COUNT+=1
         print 'Threaded request started (%d)...'%THREAD_COUNT
         input=''
         while 1:
             input += theSocket.recv(1024)
             if len(input) and input[-1]=='\n': break
         input=input.strip()

         print 'Got input: \'%s\''%input
         if input=='Is it you?':
             theSocket.sendall('Yes honey.\n')

         print 'Threaded request finished.'
         THREAD_COUNT-=1
         theEvent.set() # set the event here to tell the handler to exit


Best regards,
Ahmed


"Fortepianissimo" <fortepianissimo at yahoo.com.tw> wrote in message
news:ef08387c.0312241345.26a1430d at posting.google.com...
> Below are three simple scripts: jmSocketLib.py contains library code
> for socket server and client, server.py instantiates a server binding
> to port 50000+ (grab the first available port), and client.py
> simulates 1000 consecutive connection requests to the server (stress
> test). The client searches from port 50000 for the server, and sends a
> challenge "JM?" and expects to get a response "0_87" - otherwise
> anything that happens to own a port 50000+ would be mistaken to be the
> real server.
>
> The code:
>
> ---------- jmSocketLib.py ----------
> #!/usr/bin/env python
>
> import SocketServer,socket,threading
>
> PORT_MIN=50000
> PORT_MAX=50005
>
> THREAD_COUNT=0
>
> class JMSocketThread (threading.Thread):
>     def __init__ (self, theSocket):
>
threading.Thread.__init__(self,target=self._myRun,args=[theSocket])
>     def _myRun (self,theSocket):
>         global THREAD_COUNT
>         THREAD_COUNT+=1
>         print 'Threaded request started (%d)...'%THREAD_COUNT
>         input=''
>         while 1:
>             input += theSocket.recv(1024)
>             if len(input) and input[-1]=='\n': break
>         input=input.strip()
>
>         print 'Got input: \'%s\''%input
>         if input=='Is it you?':
>             theSocket.sendall('Yes honey.\n')
>
>         print 'Threaded request finished.'
>         THREAD_COUNT-=1
>
>
> class JMHandler (SocketServer.BaseRequestHandler):
>     def handle (self):
>         print 'Client connected...'
>         JMSocketThread(self.request).start()
>         print 'Request handed off to a thread.'
>
>
> class JMServer (SocketServer.TCPServer):
>     def __init__ (self):
>         port=PORT_MIN
>         while port<PORT_MAX:
>             try:
>                 SocketServer.TCPServer.__init__(self,('',port),JMHandler)
>                 print 'Bound port %d'%port
>                 break
>             except:
>                 port+=1
>
> class JMClient:
>     def __init__ (self):
>         port=PORT_MIN
>
>         while port<=PORT_MAX:
>             try:
>                 self.socket=socket.socket(socket.AF_INET,
> socket.SOCK_STREAM)
>                 self.socket.connect(('',port))
>                 self.socket.sendall('Is it you?\n')
>                 print 'Query sent...'
>                 reply=''
>                 while 1:
>                     reply += self.socket.recv(1024)
>                     if len(reply) and reply[-1]=='\n': break
>                 reply=reply.strip()
>
>                 print 'Got reply: \'%s\''%reply
>
>                 if reply == 'Yes honey.':
>                     print 'Found the server at port %d'%port
>                     break
>                 else: raise None
>             except:
>                 self.socket.close()
>                 port+=1
>
>
> ---------- server.py ----------
> #!/usr/bin/env python
>
> from jmSocketLib import *
>
> if __name__ == '__main__':
>     jmServer=JMServer()
>     jmServer.serve_forever()
>
> ---------- client.py ----------
> #!/usr/bin/env python
>
> from jmSocketLib import *
>
> if __name__ == '__main__':
>     # stress test
>     for i in range(1000):
>         print i
>         JMClient()
>
>
>
>
> Now the problem is, every now and then I got this error from the
> server side:
>
> ---- ERROR on server side ----
> Client connected...
> Threaded request started (1)...
> Request handed off to a thread.
> Got input: 'Is it you?'
> Exception in thread Thread-125:
> Traceback (most recent call last):
>   File "/sw/src/root-python23-2.3.2-22/sw/lib/python2.3/threading.py",
> line 436, in __bootstrap
>     self.run()
>   File "/sw/src/root-python23-2.3.2-22/sw/lib/python2.3/threading.py",
> line 416, in run
>     self.__target(*self.__args, **self.__kwargs)
>   File "/Users/ben/temp/jmSocketLib.py", line 25, in _myRun
>     theSocket.sendall('0_87\n')
>   File "<string>", line 1, in sendall
>   File "/sw/src/root-python23-2.3.2-22/sw/lib/python2.3/socket.py",
> line 143, in _dummy
>     raise error(EBADF, 'Bad file descriptor')
> error: (9, 'Bad file descriptor')
> --------------------------
>
> Of course the client then freezes:
>
>
> ---- Client output ----
> 124
> Query sent...
> (and freezes)
>
>
> Does anyone have an explanation why this didn't work? Thanks a lot!






More information about the Python-list mailing list