Anna Kratochvílová wrote:
> There is a "stop" button in the GUI of all modules. When I press it, the
> GUI dialog returns to a state where I can reinitiate the module process. But
> looking in my system monitor, the old process is still continuing.
Is it actually running, or is it a zombie?
and then line 578:
self.module.kill()
which doesn't work. I tried to call terminate(), for my Ubuntu it
works, however I have no idea why.
For a subprocess.Popen object, the only difference between .kill() and
.terminate() is that the former sends SIGKILL (which cannot be caught)
while the latter sends SIGTERM (which can be caught).
However, gcmd defines its own Popen class, derived from
subprocess.Popen, which overrides the .kill() method in an attempt to
terminate the entire process group:
def kill(self):
"""!Try to kill running process"""
if subprocess.mswindows:
import win32api
handle = win32api.OpenProcess(1, 0, self.pid)
return (0 != win32api.TerminateProcess(handle, 0))
else:
try:
os.kill(-self.pid, signal.SIGTERM) # kill whole group
except OSError:
pass
However: subprocess.Popen() doesn't create a new process group for the
child, so self.pid won't be a process group ID (PGID), so
os.kill(-self.pid, ...) won't actually do anything.
Also, it uses SIGTERM rather than SIGKILL, and silently ignores any
exceptions.
If it's desired to make the "stop" button kill the child process and
all of its descendents, the child process must be explicitly put into
a separate process group with os.setpgid() or os.setpgrp(). This must
be done after the fork() but before the execve(); it should be
possible to do this using the preexec_fn argument to the Popen
constructor.
OTOH, it might be better to just remove the overridden .kill() method
and live with the fact that any descendents of child processes won't
necessarily be terminated by the "stop" button (although in most
cases, any descendents will terminate as a consequence of their parent
terminating).
--
Glynn Clements <glynn@gclements.plus.com>