= Description = ## Please read this page. Lines prefixed with ## such as this one are comments, ## you can remove them (except for those after the "Plan" section.) ## Please follow the instructions given in those comments and the text. ## After creating the bug page, please subscribe to it! We may have questions ## that only you can answer, and if you get email when your bug changes it'll ## be much faster to get it fixed since you can answer the questions! While the standalone server is processing a request, it cannot be killed with ordinary signals (e.g. SIGINT (Ctrl-C) or SIGTERM). Only SIGKILL ("kill -9") seems to work. This is because server_standalone spawns non-daemon threads, which block the process from terminating until they exit (see http://docs.python.org/lib/thread-objects.html, under `setDaemon()`). == Steps to reproduce == ## Describe the steps needed to reproduce the bug. If we can't reproduce it, we probably can't fix it. 1. run `moin ... server standalone` in the foreground (attached to a terminal where you can use Ctrl-C to signal the process) 1. start a request that takes a while (e.g. full-text search without indexes, or linkto: search) 1. while the request is still running, hit Ctrl-C in the terminal where the server process is running 1. note that `moin` may print "Thanks for using !MoinMoin!" to stdout (or its log file), but it does *not* terminate 1. when the request finishes and `moin` sends the response to the browser, then it terminates The last two symptoms indicate that `moin` is receiving the SIGINT signal, but still keeps running. This is particularly bad if running `moin` on underpowered hardware where you really did not mean to run that unindexed full-text search. == Example == See reproduction. == Component selection == * `MoinMoin.server.server_standalone` Note: a comment in `server_standalone.py` says that the twisted server has the same problem. I have '''not''' attempted to reproduce, investigate, or fix the problem in the twisted server. I suspect the problem and the fix are similar, though. == Details == ## If you got a traceback, please save the traceback page as html and attach here: ## [[attachment:traceback.html]] ## if the bug is in this wiki, just kill the table and write: This Wiki. ## If a traceback is not available, please fill in the details here: || '''!MoinMoin Version''' || 1.7.1 || || '''OS and Version''' || Ubuntu 7.04 (feisty fawn), Linux 2.6.20 || || '''Python Version''' || 2.5.1 || || '''Server Setup''' || standalone || || '''Server Details''' || || || '''Language you are using the wiki in''' (set in the browser/UserPreferences) || en || == Workaround == `kill -9` on the server process sometimes works, but not always. (This confuses me.) = Discussion = The fix is quite easy: threads created by the server process should be daemon threads. Here is a patch for `server_standalone`: {{{ --- a/MoinMoin/server/server_standalone.py Mon Aug 18 14:49:18 2008 -0400 +++ b/MoinMoin/server/server_standalone.py Tue Aug 19 17:43:40 2008 -0400 @@ -133,6 +133,7 @@ class ThreadingServer(SimpleServer): return t = Thread(target=self.process_request_thread, args=(request, client_address)) + t.setDaemon(True) t.start() finally: self.lock.release() @@ -186,6 +187,7 @@ class ThreadPoolServer(SimpleServer): from threading import Thread for dummy in range(self.poolSize): t = Thread(target=self.serve_forever_thread) + t.setDaemon(True) t.start() SimpleServer.serve_forever(self) }}} One catch: after adding this, killing the server process works. However, I am seeing weird errors from doing that. Example: {{{ 2008-08-20 11:49:42,834 INFO MoinMoin.server.server_standalone:498 Thanks for using MoinMoin! Exception in thread Thread-4 (most likely raised during interpreter shutdown): Traceback (most recent call last): File "threading.py", line 460, in __bootstrap File "threading.py", line 440, in run File "/src/wiki/moin-1.7.1/lib/MoinMoin/server/server_standalone.py", line 220, in serve_forever_thread File "SocketServer.py", line 254, in finish_request File "/src/wiki/moin-1.7.1/lib/MoinMoin/server/server_standalone.py", line 290, in __init__ File "SocketServer.py", line 525, in __init__ : 'NoneType' object has no attribute 'exc_traceback' Unhandled exception in thread started by Error in sys.excepthook: Original exception was: }}} About half the time, moin seems to shut down cleanly on Ctrl-C (the client waiting for a response gets nothing, of course), and half the time I get that error. It always shuts down quite quickly after Ctrl-C, though, and that IMHO is the important thing. Follow-up patch is to remove the comment and debug prints from the last person to look at this: {{{ --- a/MoinMoin/server/server_standalone.py Tue Aug 19 17:43:40 2008 -0400 +++ b/MoinMoin/server/server_standalone.py Wed Aug 20 11:34:25 2008 -0400 @@ -165,11 +165,6 @@ class ThreadPoolServer(SimpleServer): This server is 5 times faster than ThreadingServer for static files, and about the same for wiki pages. - - TODO: sometimes the server won't exit on Conrol-C, and continue to - run with few threads (you can kill it with kill -9). Same problem - exist with the twisted server. When the problem is finally solved, - remove the commented debug prints. """ use_threads = True @@ -221,7 +216,6 @@ class ThreadPoolServer(SimpleServer): except: self.handle_error(request, client_address) self.close_request(request) - # sys.stderr.write('thread exiting...\n') def pop_request(self): """ Pop a request from the queue @@ -242,7 +236,6 @@ class ThreadPoolServer(SimpleServer): self.lock.wait() finally: self.lock.release() - # sys.stderr.write('thread exiting...\n') sys.exit() def die(self): @@ -258,7 +251,6 @@ class ThreadPoolServer(SimpleServer): def wake_all_threads(self): self.lock.acquire() try: - # sys.stderr.write('waking up all threads...\n') self.lock.notifyAll() finally: self.lock.release() }}} = Plan = ## This part is for Moin``Moin developers: * Priority: * Assigned to: * Status: Fixed by http://hg.moinmo.in/moin/1.7/rev/d996f53790bb ---- ## If you are a moin core developer, replace the category to Category* in these cases: ## Category MoinMoinNoBug - if this is not a bug. ## Category MoinMoinBugConfirmed - if you can confirm the bug on current code. ## Category MoinMoinBugFixed - after the bug is fixed in current code. CategoryMoinMoinBugFixed