Threaded server

Nick Craig-Wood nick at craig-wood.com
Mon Jan 14 06:30:04 EST 2008


Giampaolo Rodola' <gnewsg at gmail.com> wrote:
>  I'm trying to run an asynchronous FTP server I wrote into a thread for
>  being able to run a test suite against it.
>  The code below is the threaded FTP server code I'm using:
> 
>  class FTPd(threading.Thread):
> 
>      def __init__(self):
>          self.active = False
>          threading.Thread.__init__(self)
> 
>      def start(self, flag=None):
>          assert not self.active
>          self.flag = flag
>          threading.Thread.start(self)
> 
>      def run(self):
>          assert not self.active
>          ftpd = ftpserver.FTPServer(address, ftp_handler)
>          if self.flag:
>              self.flag.set()
>          self.active = True
>          while self.active:
>              ftpd.server_forever(timeout=1, count=1)
>          ftpd.close()
> 
>      def stop(self):
>          assert self.active
>          self.active = False
> 
>  flag = threading.Event()
>  ftpd = FTPd()
>  ftpd.start(flag)
>  flag.wait()  # wait for it to start
>  unittest.main() # run the test suite
>  ftpd.stop()
> 
>  Sometimes I get a strange error when all the tests have finished, the
>  server is stopped and Python is exiting:
> 
>  Ran 50 tests in 1.515s
> 
>  OK
>  Exception exceptions.TypeError: "'NoneType' object is not callable" in
> <bound me
>  thod FTPHandler.__del__ of <pyftpdlib.ftpserver.FTPHandler connected
>  127.0.0.1:2
>  249 at 0xa4b080>> ignored
>  Exception exceptions.TypeError: "'NoneType' object is not callable" in
> <bound me
>  thod FTPServer.__del__ of <pyftpdlib.ftpserver.FTPServer listening
>  127.0.0.1:543
>  21 at 0x9e1a30>> ignored
> 
> 
>  I sincerely don't know why that happens but it's likely because I'm
>  not using threads properly.
>  My concern is that this could be caused by a sort of race condition
>  (e.g. Python tries to exit when ftpd.close call is not yet
>  completed).

It looks like when python is shutting down, it has removed an object
the ftphandler code relies on.

I see you attempt to kill the ftp server with ftpd.stop().  That is
good, but you don't wait for the thread to finish (it might take up to
a second in ftpd.server_forever if I understand correctly).

I expect if you put a self.join() at the end of the stop() method the
problem will go away.

-- 
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick



More information about the Python-list mailing list