GNOME Bugzilla – Bug 579406
pygtk_main_watch_prepare leaks file descriptors, causing crashes if the main loop is run repeatedly
Last modified: 2009-10-29 19:31:16 UTC
I've already filed this issue on the Launchpad bug tracker: details are here: https://bugs.launchpad.net/ubuntu/+source/gtk+2.0/+bug/363245 Here's a script which reproduces the problem: from gtk import main, main_quit from gobject import threads_init, timeout_add, source_remove import sys def test(iterations, use_threads): if use_threads: threads_init() tick = 0 while tick < iterations: tick += 1 if (tick % 1000) == 0: print 'Tick', tick lasttag = timeout_add(1, main_quit) main() source_remove(lasttag) if __name__ == "__main__": if sys.argv[1:] == ['no-threads']: threads = False else: threads = True print 'Using threads:', threads test(10000, threads) print 'Done.'
Created attachment 133805 [details] [review] fix The change that really fixes the bug is the g_source_unref() call.
I can reproduce the same error using gobject only without gtk import so I think this fix don't really solve the problem: # -*- coding: utf-8 -*- from gobject import threads_init, timeout_add, source_remove import gobject import sys def test(iterations, use_threads): if use_threads: threads_init() tick = 0 while tick < iterations: loop=gobject.MainLoop() tick += 1 if (tick % 1000) == 0: print 'Tick', tick lasttag = timeout_add(1, loop.quit) loop.run() source_remove(lasttag) if __name__ == "__main__": if sys.argv[1:] == ['no-threads']: threads = False else: threads = True print 'Using threads:', threads test(10000, threads) print 'Done.' Using threads: True ** ERROR **: Cannot create main loop pipe: Too many open files aborting... Aborted
(In reply to comment #2) > I can reproduce the same error using gobject only without gtk import so I think > this fix don't really solve the problem: It does, just there is another piece of code (in PyGObject) with the same problem. I fixed that too, you can test in the repository. Don't know if it will make it to the current stable release branch though.
Thanks, it is possible to have a diffs for python-gobject 2.16.1 and 2.18 so I can apply the patch to jaunty and karmic? Nicola
Created attachment 143819 [details] [review] fix for the second bug You could extract it from git yourself ;)
Paul, seems there are yet issues with gobject and threads, look at this simple test case: # -*- coding: utf-8 -*- import gobject import time import threading gobject.threads_init() def test(): loop=gobject.MainLoop() loop.run() time.sleep(1) loop.quit() def testlaucher(iterations): for i in range(iterations): print 'Iteration:', i+1 t=threading.Thread(target=test) t.start() if __name__ == "__main__": testlaucher(10000) print 'Done.' here is the output: .... .... Iteration: 559 Iteration: 560 ** ERROR **: Cannot create main loop pipe: Too many open files aborting... Abortito seems two fd are created when loop=gobject.MainLoop() is called and are never given back when the thread exit, maybe a better solution would be: 1) allocate the fd on "loop.run()" 2) release the fd on "loop.quit()" regards Nicola
same issue even if you remove the line time.sleep(1) Nicola
This is not valid. After you call 'loop.run()', the thread is stuck and 'loop.quit()' is never executed. So, you create hundreds of threads each with its own stuck loop --- of course you run out of files.