Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kill the entire subtree when killing child process #143

Merged
merged 3 commits into from
Sep 22, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions pyfarm/jobtypes/core/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import os

from psutil import Process, NoSuchProcess
from twisted.internet import reactor
from twisted.internet.protocol import ProcessProtocol as _ProcessProtocol

from pyfarm.agent.logger import getLogger
Expand Down Expand Up @@ -128,8 +129,12 @@ def processEnded(self, reason):
only want to notify the parent job type once the process has freed
up the last bit of resources.
"""
self.__ended = True
self.jobtype._process_stopped(self, reason)
try:
self.__ended = True
self.jobtype._process_stopped(self, reason)
except Exception as e:
logger.error("Exception caught while running "
"jobtype._process_stopped: %s", e)

def outReceived(self, data):
"""Called when the process emits on stdout"""
Expand All @@ -149,18 +154,38 @@ def kill(self):
"""Kills the underlying process, if running."""
logger.info("Killing %s", self)
try:
self.process.signalProcess("KILL")
process = self.psutil_process
if not process:
return
children = process.children(recursive=True)
process.kill()
except Exception as e: # pragma: no cover
logger.warning("Cannot kill %s: %s.", self, e)

def kill_children(children):
for child in children:
child.kill()
if children:
reactor.callLater(2, kill_children, children)

def terminate(self):
"""Terminates the underlying process, if running."""
logger.info("Terminating %s", self)
try:
self.process.signalProcess("TERM")
process = self.psutil_process
if not process:
return
children = process.children(recursive=True)
process.terminate()
except Exception as e: # pragma: no cover
logger.warning("Cannot terminate %s: %s.", self, e)

def terminate_children(children):
for child in children:
child.terminate()
if children:
reactor.callLater(2, terminate_children, children)

def interrupt(self):
"""Interrupts the underlying process, if running."""
logger.info("Interrupt %s", self)
Expand Down