psychoone7 / pyftpdlib

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

100% cpu usage on ThreadedFtpServer #245

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. run example ThreadedFTPServer
2. connect with filezilla - or any ftp client
3. close filezilla

What is the expected output?
nothing

What do you see instead?
100% cpu usage

What version of pyftpdlib are you using? On what operating system? Which
Python version?
ubuntu 12.04 64 bit though happens with every 

Please provide any additional information below.
on servers.py I added these lines in def _loop:
....
            while (socket_map or tasks) and not self._exit.is_set():
                import time
                time.sleep(1)
                print "============================================="                
                print "socket_map", socket_map
                print "tasks", tasks
                print "============================================="

when you connect you start seeing output:
socket_map {5: <pyftpdlib.handlers.FTPHandler (addr=127.0.0.1:52383, 
user=u'user') at 0x7f96a406f6c8>}
tasks [<<pyftpdlib.ioloop._CallEvery object at 0x7f96a45109e0> args=[], 
kwargs={}, cancelled=True, secs=300>, <<bound method FTPHandler.handle_timeout 
of <pyftpdlib.handlers.FTPHandler (addr=127.0.0.1:52383, user=u'user') at 
0x7f96a406f6c8>> args=[], kwargs={}, cancelled=False, secs=300>]

when you disconnect you see output 
socket_map {}
tasks [<<pyftpdlib.ioloop._CallEvery object at 0x7f96a45109e0> args=[], 
kwargs={}, cancelled=True, secs=300>, <<pyftpdlib.ioloop._CallLater object at 
0x7f96a4074d70> args=[], kwargs={}, cancelled=True, secs=300>]

and the thread loops until it timeouts (for 5 minutes), altough all tasks are 
cancelled. this causes loooping like crazy - since there is no socket to listen 
- and burns the cpus.

simply clearing the tasks if there is no socket solves the problem (addding 
something like this in _loop function )

                    if socket_map:
                        poll(timeout=soonest_timeout)
                    else:
                        tasks = []

solves the problem but not really sure if this is the correct way, or might 
make other problems.

Hope I could have explained the problem, please feel free to ask if you need 
more details.

Original issue reported on code.google.com by aybars.b...@gmail.com on 4 Apr 2013 at 4:17

GoogleCodeExporter commented 9 years ago
I cannot reproduce the issue on Linux.
What happens if you do this?

- while (socket_map or tasks) and not self._exit.is_set():
+ while socket_map and not self._exit.is_set():

Original comment by g.rodola on 4 Apr 2013 at 4:42

GoogleCodeExporter commented 9 years ago
Thanks for your fast reply,

If i remove tasks and change the line to 

while socket_map and not self._exit.is_set():

it works perfectly. 

Original comment by aybars.b...@gmail.com on 4 Apr 2013 at 4:49

GoogleCodeExporter commented 9 years ago
Forget about that: it breaks tests.
Are you able to provide a Python script which reproduces the problem?
I tried to connect with Filezilla, login and disconnect but nothing happened.
I used 
https://code.google.com/p/pyftpdlib/source/browse/trunk/demo/multi_thread_ftp.py
 as server.

Original comment by g.rodola on 4 Apr 2013 at 4:51

GoogleCodeExporter commented 9 years ago
Ok, I managed to reproduce the issue (sorry =)).
I'm gonna look into it.

Original comment by g.rodola on 4 Apr 2013 at 4:58

GoogleCodeExporter commented 9 years ago
yes, attached thserver.py though its the same as demo multi threaded 

I'll try to give more details. Here is the steps i do, I run thserver.py, 
connect with filezilla, then download a file, then close filezilla, in htop the 
cpu goes high, and the thread doesnt end until 5 minutes. so if you connect 
with a couple of sessions, or start downloading big files and exit, you can 
reach 100% cpu usage.

Attached htop screenshot

Original comment by aybars.b...@gmail.com on 4 Apr 2013 at 5:02

Attachments:

GoogleCodeExporter commented 9 years ago
Fixed in r1203.
Will release a new version soon as this makes ThreadedFtpServer unusable. 

Original comment by g.rodola on 5 Apr 2013 at 11:56

GoogleCodeExporter commented 9 years ago

Original comment by g.rodola on 5 Apr 2013 at 11:56

GoogleCodeExporter commented 9 years ago

Original comment by g.rodola on 9 Apr 2013 at 2:47

GoogleCodeExporter commented 9 years ago

Original comment by g.rodola on 9 Apr 2013 at 4:29

GoogleCodeExporter commented 9 years ago
Hi,

Sorry to bug you again, but I can repeat the problem, after sockets are 
disconnected, the tasks are still there continuesly looping and hogging all the 
cpu

after heapify, ioloop.sched._tasks gets emptied, but tasks are still there, i 
am not really sure why.

on servers.py at 337:
                        if not socket_map:
                            print ">>>>>>>>>>>>>>>>>", tasks, ioloop.sched._tasks
                            time.sleep(1)
                            ioloop.sched.reheapify() # get rid of cancel()led calls
                            soonest_timeout = sched_poll()
                            if soonest_timeout:
                                time.sleep(min(soonest_timeout, 1))

I can try to write a unit test if you want ?

Original comment by aybars.b...@gmail.com on 11 Apr 2013 at 1:21

GoogleCodeExporter commented 9 years ago
Shit!
Yes please, or at least print this:

                            ...
                            soonest_timeout = sched_poll()
                            print tasks
                            if soonest_timeout:
                                time.sleep(min(soonest_timeout, 1))

Original comment by g.rodola on 11 Apr 2013 at 1:24

GoogleCodeExporter commented 9 years ago
Hi,

I modified the code to this, 

                    if tasks:
                        soonest_timeout = sched_poll()
                        print "tasks====================="
                        print tasks
                        # Handle the case where socket_map is emty but some
                        # cancelled scheduled calls are still around causing
                        # this while loop to hog CPU resources.
                        # In theory this should never happen as all the sched
                        # functions are supposed to be cancel()ed on close()
                        # but by using threads we can incur into
                        # synchronization issues such as this one.
                        # https://code.google.com/p/pyftpdlib/issues/detail?id=245
                        if not socket_map:
                            print "!!!!!!!!!! sockets disconnected !!!!!!!!!!!!!!!!"
                            time.sleep(1)
                            ioloop.sched.reheapify() # get rid of cancel()led calls
                            soonest_timeout = sched_poll()
                            if soonest_timeout:
                                time.sleep(min(soonest_timeout, 1))

attached is the output, hope it helps, i'll try to add a test case too.

ps: i connect with filezilla, download one or two files and disconnect.

Original comment by aybars.b...@gmail.com on 11 Apr 2013 at 1:35

Attachments:

GoogleCodeExporter commented 9 years ago
Ok, I should have now fixed it in r1215.
Can you please confirm that fixes the problem?

Original comment by g.rodola on 17 Apr 2013 at 6:04

GoogleCodeExporter commented 9 years ago

Original comment by g.rodola on 19 Apr 2013 at 12:49

GoogleCodeExporter commented 9 years ago
Sorry for the late reply, cloned from svn, then I double checked, triple 
checked and it works like charm.

Thank you so much.

Original comment by aybars.b...@gmail.com on 19 Apr 2013 at 3:05

GoogleCodeExporter commented 9 years ago

Original comment by g.rodola on 22 Apr 2013 at 2:50