[Pkg-privacy-commits] [pyptlib] 126/136: use Windows JobObjects to have all children killed when the parent process dies unexpectedly
Ximin Luo
infinity0 at moszumanska.debian.org
Sat Aug 22 13:25:19 UTC 2015
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch master
in repository pyptlib.
commit 97be8ad7c74e051fa535b976b583e0032964f169
Author: Ximin Luo <infinity0 at gmx.com>
Date: Tue Oct 29 20:47:38 2013 +0000
use Windows JobObjects to have all children killed when the parent process dies unexpectedly
---
pyptlib/util/subproc.py | 48 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/pyptlib/util/subproc.py b/pyptlib/util/subproc.py
index 0f02ce8..3ec28d2 100644
--- a/pyptlib/util/subproc.py
+++ b/pyptlib/util/subproc.py
@@ -16,9 +16,18 @@ import time
mswindows = (sys.platform == "win32")
if mswindows:
+ """
+ Set KILL_CHILDREN_ON_DEATH=1 in the environment to automatically kill all
+ descendents when this process dies.
+ """
+ # TODO(infinity0): write a test for this, similar to test_killall_kill
+ # Note: setting this to True defeats the point of some of the tests, so
+ # keep the default value as False. Perhaps we could make that work better.
+ _kill_children_on_death = bool(os.getenv("KILL_CHILDREN_ON_DEATH", 0))
+
from ctypes import byref, windll, WinError
from ctypes.wintypes import DWORD
- import win32api, win32con, win32job
+ import win32api, win32con, win32job, win32process
_CHILD_PROCS = []
# TODO(infinity0): add functionality to detect when any child dies, and
@@ -32,10 +41,37 @@ a = inspect.getargspec(subprocess.Popen.__init__)
_Popen_defaults = zip(a.args[-len(a.defaults):],a.defaults); del a
if mswindows:
# required for os.kill() to work
+ _Popen_creationflags = subprocess.CREATE_NEW_PROCESS_GROUP
+
+ if _kill_children_on_death:
+ _chJob = win32job.CreateJobObject(None, "")
+ if not _chJob:
+ raise WinError()
+
+ chJeli = win32job.QueryInformationJobObject(
+ _chJob, win32job.JobObjectExtendedLimitInformation)
+ # JOB_OBJECT_LIMIT_BREAKAWAY_OK allows children to assign grandchildren
+ # to their own jobs
+ chJeli['BasicLimitInformation']['LimitFlags'] |= (
+ win32job.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE |
+ win32job.JOB_OBJECT_LIMIT_BREAKAWAY_OK)
+
+ if win32job.SetInformationJobObject(
+ _chJob, win32job.JobObjectExtendedLimitInformation, chJeli) == 0:
+ raise WinError()
+ del chJeli
+
+ # If we already belong to a JobObject, our children are auto-assigned
+ # to that and AssignProcessToJobObject(ch, _chJob) fails. This flag
+ # prevents this auto-assignment, as long as the parent JobObject has
+ # JOB_OBJECT_LIMIT_BREAKAWAY_OK set on it as well.
+ _Popen_creationflags |= win32process.CREATE_BREAKAWAY_FROM_JOB
+
tmp = dict(_Popen_defaults)
- tmp['creationflags'] |= subprocess.CREATE_NEW_PROCESS_GROUP
+ tmp['creationflags'] |= _Popen_creationflags
_Popen_defaults = tmp.items()
- del tmp
+ del tmp, _Popen_creationflags
+
class Popen(subprocess.Popen):
"""Wrapper for subprocess.Popen that tracks every child process.
@@ -64,6 +100,12 @@ class Popen(subprocess.Popen):
subprocess.Popen.__init__(self, *args, **kwargs)
_CHILD_PROCS.append(self)
+ if mswindows and _kill_children_on_death:
+ handle = windll.kernel32.OpenProcess(
+ win32con.SYNCHRONIZE | win32con.PROCESS_SET_QUOTA | win32con.PROCESS_TERMINATE, 0, self.pid)
+ if win32job.AssignProcessToJobObject(_chJob, handle) == 0:
+ raise WinError()
+
# TODO(infinity0): perhaps replace Popen.std* with wrapped file objects
# that don't buffer readlines() et. al. Currently one must avoid these and
# use while/readline(); see man page for "python -u" for more details.
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/pyptlib.git
More information about the Pkg-privacy-commits
mailing list