4udak / pyftpdlib

Automatically exported from code.google.com/p/pyftpdlib
Other
1 stars 1 forks source link

Running multiple instances of ftp server in different threads causes transfers crash. #182

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. from main(), create 2 threads that run a different FTP server (FTP and FTPS 
for example) and launch serve_forever()
2. Start some upload on one of the FTP.
3. Exception is raised in asyncore.py : Errno 11 Ressource temporarily 
unavailable.

What version of pyftpdlib are you using? On what operating system? Which Python 
version?
On Linux - Ubuntu 10.4 - pyftpdlib 0.6 - python 2.6

Exception detail:

[11/Aug/2011:15:46:35] [ftp_server.py:log:158]  INFO - [Secure FTP Server] 
X.X.X.X:2594 ==> 125 Data connection already open. Transfer starting.
[11/Aug/2011:15:46:36] [ftp_server.py:log:158]  INFO - [Secure FTP Server ERROR] 
Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/pyftpdlib-0.6.0-py2.6.egg/pyftpdlib/ftpserver.py", line 923, in handle_read
    chunk = self.recv(self.ac_in_buffer_size)
  File "/usr/lib/python2.6/asyncore.py", line 365, in recv
    data = self.socket.recv(buffer_size)
error: [Errno 11] Resource temporarily unavailable

[11/Aug/2011:15:46:36] [ftp_server.py:log:158]  INFO - [Secure FTP Server] 
X.X.X.X:2594 ==> 426 Resource temporarily unavailable; transfer aborted.

To clarify, I want to run a FTP server and a FTPS server. So from my "main", I 
run 2 threads, one for FTP and one for FTPS. Threading class is derived from 
threading.Thread and in the run() method, I setup my FTP objects (authorizer, 
handler, server) and I call server.serve_forever().
Everything works fine until I try a transfer. Every seconds or so, the 
exception happens.

If I run only one thread, it all works fine.

Is there something in asyncore that is not thread safe or am I missing 
something?

For information, I dont use the same data port range for the 2 instances 
running.

Thanks in advance for you help.

Also, would like to say thanks because pyftpdlib is an awesome piece of code. 
Really useful, really powerful.

Cheers,
Ronan

Original issue reported on code.google.com by ronan.de...@gmail.com on 11 Aug 2011 at 1:56

GoogleCodeExporter commented 9 years ago
Why are you using threads in the first place?  Take a look at 
http://groups.google.com/group/pyftpdlib/browse_thread/thread/63a6d9a6425f3560

Original comment by d...@devicenull.org on 12 Aug 2011 at 7:35

GoogleCodeExporter commented 9 years ago
Ah cool, that means I can create one FTP server object, then one FTPS server 
object and then I call serve_forever method on the class and it will serve FTP 
and FTPS at the same time, am I right? That' cool then. 
I will try that next week. Thanks. 

Original comment by ronan.de...@gmail.com on 13 Aug 2011 at 10:02

GoogleCodeExporter commented 9 years ago
First, thanks a lot, that worked.

Ok, on version 0.6, the following works : 

            ftp_server_1 = ftp_server.CreateFTPServer(...)
            ftps_server_2 = ftp_server.CreateSecureFTPServer(...)

            ftps_server_2.serve_forever()

But calling does not work as serve_forever() does not seem to be a class method:
            pyftpdlib.ftp_server.serve_forever()
Is it planned for next version as the enhancement seems quite recent?

Also, 2 totally unrelated notes : 
 - it would be great to have the ability to have different loggers per server object and not for the whole lib.
 - it would also be great to be able to configure that the SIGINT signal should be caught or not by server_forever().

Cheers,
R.

Original comment by ronan.de...@gmail.com on 16 Aug 2011 at 1:45

GoogleCodeExporter commented 9 years ago
I'm unsure of what release it would end up being it, but I'd assume the change 
to a class method would come in the next one.

Original comment by d...@devicenull.org on 17 Aug 2011 at 7:08

GoogleCodeExporter commented 9 years ago
> it would also be great to be able to configure that the SIGINT signal should 
be 
> caught or not by server_forever().

You can do so by specifying the "count" argument:

while 1:
    try
        server.serve_forever(count=1)
    except KeyboardInterrupt:
        ...

Original comment by g.rodola on 5 Sep 2011 at 3:25

GoogleCodeExporter commented 9 years ago
Closing this out as invalid.

Original comment by g.rodola on 31 Oct 2011 at 4:55