python-manhole
python-manhole copied to clipboard
manhole socket not removed when terminating a process
Although manhole register the removal function using atexit module, the removal function is not run when sending the process SIGTERM.
To reproduce:
-
Create a script::
import manhole import time manhole.install(socket_path='exit.manhole') time.sleep(30)
-
Run the script in the backround
python exit.py &
-
And terminate it
kill
The removal function is not called, and manhole socket is not removed.
Tested on Fedora 19.
This seems faulty implementation of atexit module.
Workarounds:
- terminate the process using SIGINT
- manually remove the socket in the application - easy when using socket_path option
Adding manhole.uninstall() would be useful for application that want to ensure that the manhole is cleanup properly.
manhole.uninstall() should
- remove the socket from the file system. Connected client should not be affected by this.
- set a flag, so the manhole thread will exit
- wakeup the manhole thread, in case it is blocking on accept - I think that closing the manhole socket should work.
This of course will not help manhole inherited in a sub process, but it will be good enough for me, since I'm using socket_path.
Workaround: define a signal hanlder for SIGTERM:
import signal
import sys
def handle_sigterm(signo, frame):
print "Terminated"
sys.exit(128 + signo)
signal.signal(signal.SIGTERM, handle_sigterm)
Should this be part of the documentation ?
Thanks, -- Ionel M.
On Sat, Sep 6, 2014 at 10:35 PM, Nir Soffer [email protected] wrote:
Workaround: define a signal hanlder for SIGTERM:
import signal import sys
def handle_sigterm(signo, frame): print "Terminated" sys.exit(128 + signo)
signal.signal(signal.SIGTERM, handle_sigterm)
— Reply to this email directly or view it on GitHub https://github.com/ionelmc/python-manhole/issues/8#issuecomment-54725795 .
I guess it should, maybe under "Known issues".
I think we can register the signal handler in manhole, checking that no signal handler was installed before that:
if signal.getsignal(signal.SIGTERM) == signal.SIG_DFL:
signal.signal(signal.SIGTERM, _handle_sigterm)
If a user install sigterm handler after that, we don't care, since atexit will be called. If the user did not install one, our handler will make sure the socket will be cleaned.
The only issue is that installing signals is possible only from the main thread, so manhole.install() will have to be called from the main thread. I don't think this is an issue since anyone will call this from the main thread anyway.
I think this issue is resolved by #8, so we can close it now.