Threaded server: what's wrong with this code?

Benjamin Han bhan at andrew.cmu.edu
Thu Dec 25 13:27:40 EST 2003


Thank you for the reply, my questions follow:

On Thu, 25 Dec 2003, Ahmed MOHAMED ALI wrote:
> 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.

Maybe my understanding is wrong - but when you pass self.request the reference
count should still be greater than 0, so it shouldn't be garbage-collected?

> 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

Minor: should be threading.Event()

>          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

But this solution sort of defeats the purpose of using threads? Because
now every request must wait until the last one is fully processed...

I'd appreciate more comments on these questions. Thank you!

Ben


>
>
> "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