Index: src/third_party/pylib/mozrunner/winprocess.py |
=================================================================== |
--- src/third_party/pylib/mozrunner/winprocess.py (revision 9275) |
+++ src/third_party/pylib/mozrunner/winprocess.py (working copy) |
@@ -1,381 +0,0 @@ |
-# A module to expose various thread/process/job related structures and |
-# methods from kernel32 |
-# |
-# The MIT License |
-# |
-# Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se> |
-# |
-# Additions and modifications written by Benjamin Smedberg |
-# <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation |
-# <http://www.mozilla.org/> |
-# |
-# More Modifications |
-# Copyright (c) 2006-2007 by Mike Taylor <bear@code-bear.com> |
-# Copyright (c) 2007-2008 by Mikeal Rogers <mikeal@mozilla.com> |
-# |
-# By obtaining, using, and/or copying this software and/or its |
-# associated documentation, you agree that you have read, understood, |
-# and will comply with the following terms and conditions: |
-# |
-# Permission to use, copy, modify, and distribute this software and |
-# its associated documentation for any purpose and without fee is |
-# hereby granted, provided that the above copyright notice appears in |
-# all copies, and that both that copyright notice and this permission |
-# notice appear in supporting documentation, and that the name of the |
-# author not be used in advertising or publicity pertaining to |
-# distribution of the software without specific, written prior |
-# permission. |
-# |
-# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
-# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. |
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
-# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
-# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
- |
-from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE |
-from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPWSTR, UINT, WORD |
-from qijo import QueryInformationJobObject |
- |
-LPVOID = c_void_p |
-LPBYTE = POINTER(BYTE) |
-LPDWORD = POINTER(DWORD) |
-LPBOOL = POINTER(BOOL) |
- |
-def ErrCheckBool(result, func, args): |
- """errcheck function for Windows functions that return a BOOL True |
- on success""" |
- if not result: |
- raise WinError() |
- return args |
- |
- |
-# AutoHANDLE |
- |
-class AutoHANDLE(HANDLE): |
- """Subclass of HANDLE which will call CloseHandle() on deletion.""" |
- |
- CloseHandleProto = WINFUNCTYPE(BOOL, HANDLE) |
- CloseHandle = CloseHandleProto(("CloseHandle", windll.kernel32)) |
- CloseHandle.errcheck = ErrCheckBool |
- |
- def Close(self): |
- if self.value and self.value != HANDLE(-1).value: |
- self.CloseHandle(self) |
- self.value = 0 |
- |
- def __del__(self): |
- self.Close() |
- |
- def __int__(self): |
- return self.value |
- |
-def ErrCheckHandle(result, func, args): |
- """errcheck function for Windows functions that return a HANDLE.""" |
- if not result: |
- raise WinError() |
- return AutoHANDLE(result) |
- |
-# PROCESS_INFORMATION structure |
- |
-class PROCESS_INFORMATION(Structure): |
- _fields_ = [("hProcess", HANDLE), |
- ("hThread", HANDLE), |
- ("dwProcessID", DWORD), |
- ("dwThreadID", DWORD)] |
- |
- def __init__(self): |
- Structure.__init__(self) |
- |
- self.cb = sizeof(self) |
- |
-LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION) |
- |
-# STARTUPINFO structure |
- |
-class STARTUPINFO(Structure): |
- _fields_ = [("cb", DWORD), |
- ("lpReserved", LPWSTR), |
- ("lpDesktop", LPWSTR), |
- ("lpTitle", LPWSTR), |
- ("dwX", DWORD), |
- ("dwY", DWORD), |
- ("dwXSize", DWORD), |
- ("dwYSize", DWORD), |
- ("dwXCountChars", DWORD), |
- ("dwYCountChars", DWORD), |
- ("dwFillAttribute", DWORD), |
- ("dwFlags", DWORD), |
- ("wShowWindow", WORD), |
- ("cbReserved2", WORD), |
- ("lpReserved2", LPBYTE), |
- ("hStdInput", HANDLE), |
- ("hStdOutput", HANDLE), |
- ("hStdError", HANDLE) |
- ] |
-LPSTARTUPINFO = POINTER(STARTUPINFO) |
- |
-SW_HIDE = 0 |
- |
-STARTF_USESHOWWINDOW = 0x01 |
-STARTF_USESIZE = 0x02 |
-STARTF_USEPOSITION = 0x04 |
-STARTF_USECOUNTCHARS = 0x08 |
-STARTF_USEFILLATTRIBUTE = 0x10 |
-STARTF_RUNFULLSCREEN = 0x20 |
-STARTF_FORCEONFEEDBACK = 0x40 |
-STARTF_FORCEOFFFEEDBACK = 0x80 |
-STARTF_USESTDHANDLES = 0x100 |
- |
-# EnvironmentBlock |
- |
-class EnvironmentBlock: |
- """An object which can be passed as the lpEnv parameter of CreateProcess. |
- It is initialized with a dictionary.""" |
- |
- def __init__(self, dict): |
- if not dict: |
- self._as_parameter_ = None |
- else: |
- values = ["%s=%s" % (key, value) |
- for (key, value) in dict.iteritems()] |
- values.append("") |
- self._as_parameter_ = LPCWSTR("\0".join(values)) |
- |
-# CreateProcess() |
- |
-CreateProcessProto = WINFUNCTYPE(BOOL, # Return type |
- LPCWSTR, # lpApplicationName |
- LPWSTR, # lpCommandLine |
- LPVOID, # lpProcessAttributes |
- LPVOID, # lpThreadAttributes |
- BOOL, # bInheritHandles |
- DWORD, # dwCreationFlags |
- LPVOID, # lpEnvironment |
- LPCWSTR, # lpCurrentDirectory |
- LPSTARTUPINFO, # lpStartupInfo |
- LPPROCESS_INFORMATION # lpProcessInformation |
- ) |
- |
-CreateProcessFlags = ((1, "lpApplicationName", None), |
- (1, "lpCommandLine"), |
- (1, "lpProcessAttributes", None), |
- (1, "lpThreadAttributes", None), |
- (1, "bInheritHandles", True), |
- (1, "dwCreationFlags", 0), |
- (1, "lpEnvironment", None), |
- (1, "lpCurrentDirectory", None), |
- (1, "lpStartupInfo"), |
- (2, "lpProcessInformation")) |
- |
-def ErrCheckCreateProcess(result, func, args): |
- ErrCheckBool(result, func, args) |
- # return a tuple (hProcess, hThread, dwProcessID, dwThreadID) |
- pi = args[9] |
- return AutoHANDLE(pi.hProcess), AutoHANDLE(pi.hThread), pi.dwProcessID, pi.dwThreadID |
- |
-CreateProcess = CreateProcessProto(("CreateProcessW", windll.kernel32), |
- CreateProcessFlags) |
-CreateProcess.errcheck = ErrCheckCreateProcess |
- |
-# flags for CreateProcess |
-CREATE_BREAKAWAY_FROM_JOB = 0x01000000 |
-CREATE_DEFAULT_ERROR_MODE = 0x04000000 |
-CREATE_NEW_CONSOLE = 0x00000010 |
-CREATE_NEW_PROCESS_GROUP = 0x00000200 |
-CREATE_NO_WINDOW = 0x08000000 |
-CREATE_SUSPENDED = 0x00000004 |
-CREATE_UNICODE_ENVIRONMENT = 0x00000400 |
- |
-# flags for job limit information |
-# see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx |
-JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800 |
-JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000 |
- |
-# XXX these flags should be documented |
-DEBUG_ONLY_THIS_PROCESS = 0x00000002 |
-DEBUG_PROCESS = 0x00000001 |
-DETACHED_PROCESS = 0x00000008 |
- |
-# CreateJobObject() |
- |
-CreateJobObjectProto = WINFUNCTYPE(HANDLE, # Return type |
- LPVOID, # lpJobAttributes |
- LPCWSTR # lpName |
- ) |
- |
-CreateJobObjectFlags = ((1, "lpJobAttributes", None), |
- (1, "lpName", None)) |
- |
-CreateJobObject = CreateJobObjectProto(("CreateJobObjectW", windll.kernel32), |
- CreateJobObjectFlags) |
-CreateJobObject.errcheck = ErrCheckHandle |
- |
-# AssignProcessToJobObject() |
- |
-AssignProcessToJobObjectProto = WINFUNCTYPE(BOOL, # Return type |
- HANDLE, # hJob |
- HANDLE # hProcess |
- ) |
-AssignProcessToJobObjectFlags = ((1, "hJob"), |
- (1, "hProcess")) |
-AssignProcessToJobObject = AssignProcessToJobObjectProto( |
- ("AssignProcessToJobObject", windll.kernel32), |
- AssignProcessToJobObjectFlags) |
-AssignProcessToJobObject.errcheck = ErrCheckBool |
- |
-# GetCurrentProcess() |
-# because os.getPid() is way too easy |
-GetCurrentProcessProto = WINFUNCTYPE(HANDLE # Return type |
- ) |
-GetCurrentProcessFlags = () |
-GetCurrentProcess = GetCurrentProcessProto( |
- ("GetCurrentProcess", windll.kernel32), |
- GetCurrentProcessFlags) |
-GetCurrentProcess.errcheck = ErrCheckHandle |
- |
-# IsProcessInJob() |
-try: |
- IsProcessInJobProto = WINFUNCTYPE(BOOL, # Return type |
- HANDLE, # Process Handle |
- HANDLE, # Job Handle |
- LPBOOL # Result |
- ) |
- IsProcessInJobFlags = ((1, "ProcessHandle"), |
- (1, "JobHandle", HANDLE(0)), |
- (2, "Result")) |
- IsProcessInJob = IsProcessInJobProto( |
- ("IsProcessInJob", windll.kernel32), |
- IsProcessInJobFlags) |
- IsProcessInJob.errcheck = ErrCheckBool |
-except AttributeError: |
- # windows 2k doesn't have this API |
- def IsProcessInJob(process): |
- return False |
- |
- |
-# ResumeThread() |
- |
-def ErrCheckResumeThread(result, func, args): |
- if result == -1: |
- raise WinError() |
- |
- return args |
- |
-ResumeThreadProto = WINFUNCTYPE(DWORD, # Return type |
- HANDLE # hThread |
- ) |
-ResumeThreadFlags = ((1, "hThread"),) |
-ResumeThread = ResumeThreadProto(("ResumeThread", windll.kernel32), |
- ResumeThreadFlags) |
-ResumeThread.errcheck = ErrCheckResumeThread |
- |
-# TerminateProcess() |
- |
-TerminateProcessProto = WINFUNCTYPE(BOOL, # Return type |
- HANDLE, # hProcess |
- UINT # uExitCode |
- ) |
-TerminateProcessFlags = ((1, "hProcess"), |
- (1, "uExitCode", 127)) |
-TerminateProcess = TerminateProcessProto( |
- ("TerminateProcess", windll.kernel32), |
- TerminateProcessFlags) |
-TerminateProcess.errcheck = ErrCheckBool |
- |
-# TerminateJobObject() |
- |
-TerminateJobObjectProto = WINFUNCTYPE(BOOL, # Return type |
- HANDLE, # hJob |
- UINT # uExitCode |
- ) |
-TerminateJobObjectFlags = ((1, "hJob"), |
- (1, "uExitCode", 127)) |
-TerminateJobObject = TerminateJobObjectProto( |
- ("TerminateJobObject", windll.kernel32), |
- TerminateJobObjectFlags) |
-TerminateJobObject.errcheck = ErrCheckBool |
- |
-# WaitForSingleObject() |
- |
-WaitForSingleObjectProto = WINFUNCTYPE(DWORD, # Return type |
- HANDLE, # hHandle |
- DWORD, # dwMilliseconds |
- ) |
-WaitForSingleObjectFlags = ((1, "hHandle"), |
- (1, "dwMilliseconds", -1)) |
-WaitForSingleObject = WaitForSingleObjectProto( |
- ("WaitForSingleObject", windll.kernel32), |
- WaitForSingleObjectFlags) |
- |
-INFINITE = -1 |
-WAIT_TIMEOUT = 0x0102 |
-WAIT_OBJECT_0 = 0x0 |
-WAIT_ABANDONED = 0x0080 |
- |
-# GetExitCodeProcess() |
- |
-GetExitCodeProcessProto = WINFUNCTYPE(BOOL, # Return type |
- HANDLE, # hProcess |
- LPDWORD, # lpExitCode |
- ) |
-GetExitCodeProcessFlags = ((1, "hProcess"), |
- (2, "lpExitCode")) |
-GetExitCodeProcess = GetExitCodeProcessProto( |
- ("GetExitCodeProcess", windll.kernel32), |
- GetExitCodeProcessFlags) |
-GetExitCodeProcess.errcheck = ErrCheckBool |
- |
-def CanCreateJobObject(): |
- currentProc = GetCurrentProcess() |
- if IsProcessInJob(currentProc): |
- jobinfo = QueryInformationJobObject(HANDLE(0), 'JobObjectExtendedLimitInformation') |
- limitflags = jobinfo['BasicLimitInformation']['LimitFlags'] |
- return bool(limitflags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) or bool(limitflags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK) |
- else: |
- return True |
- |
-### testing functions |
- |
-def parent(): |
- print 'Starting parent' |
- currentProc = GetCurrentProcess() |
- if IsProcessInJob(currentProc): |
- print >> sys.stderr, "You should not be in a job object to test" |
- sys.exit(1) |
- assert CanCreateJobObject() |
- print 'File: %s' % __file__ |
- command = [sys.executable, __file__, '-child'] |
- print 'Running command: %s' % command |
- process = Popen(command) |
- process.kill() |
- code = process.returncode |
- print 'Child code: %s' % code |
- assert code == 127 |
- |
-def child(): |
- print 'Starting child' |
- currentProc = GetCurrentProcess() |
- injob = IsProcessInJob(currentProc) |
- print "Is in a job?: %s" % injob |
- can_create = CanCreateJobObject() |
- print 'Can create job?: %s' % can_create |
- process = Popen('c:\\windows\\notepad.exe') |
- assert process._job |
- jobinfo = QueryInformationJobObject(process._job, 'JobObjectExtendedLimitInformation') |
- print 'Job info: %s' % jobinfo |
- limitflags = jobinfo['BasicLimitInformation']['LimitFlags'] |
- print 'LimitFlags: %s' % limitflags |
- process.kill() |
- |
-if __name__ == '__main__': |
- import sys |
- from killableprocess import Popen |
- nargs = len(sys.argv[1:]) |
- if nargs: |
- if nargs != 1 or sys.argv[1] != '-child': |
- raise AssertionError('Wrong flags; run like `python /path/to/winprocess.py`') |
- child() |
- else: |
- parent() |