예제 #1
0
    def winpopen4(orig, cmd, env=None, newlines=False, bufsize=-1):
        """Same as util.popen4, but manually creates an input pipe with a
        larger than default buffer"""
        import msvcrt

        if sys.version_info[0] < 3:
            import _subprocess

            handles = _subprocess.CreatePipe(None, pipei_bufsize)
            rfd, wfd = [msvcrt.open_osfhandle(h, 0) for h in handles]
        else:
            import _winapi

            handles = _winapi.CreatePipe(None, pipei_bufsize)
            rfd, wfd = [msvcrt.open_osfhandle(h, 0) for h in handles]
            handles = [subprocess.Handle(h) for h in handles]

        handles[0].Detach()
        handles[1].Detach()
        p = subprocess.Popen(
            cmd,
            shell=True,
            bufsize=bufsize,
            close_fds=False,
            stdin=rfd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            universal_newlines=newlines,
            env=env,
        )
        p.stdin = util.fdopen(wfd, "wb", bufsize)
        return p.stdin, p.stdout, p.stderr, p
예제 #2
0
 def _make_inheritable_handle(fd):
     """Return a duplicate of handle, which is inheritable"""
     h = _winapi.DuplicateHandle(_winapi.GetCurrentProcess(),
                                 msvcrt.get_osfhandle(fd),
                                 _winapi.GetCurrentProcess(), 0, 1,
                                 _winapi.DUPLICATE_SAME_ACCESS)
     return subprocess.Handle(h)
예제 #3
0
 def make_inheritable_handle(fd):
     """Create inheritable duplicate of handle from file descriptor"""
     h = _winapi.DuplicateHandle(_winapi.GetCurrentProcess(),
                                 msvcrt.get_osfhandle(fd),
                                 _winapi.GetCurrentProcess(), 0, 1,
                                 _winapi.DUPLICATE_SAME_ACCESS)
     return subprocess.Handle(h)
예제 #4
0
파일: utils.py 프로젝트: ouliuquan/ray
def detect_fate_sharing_support_win32():
    global win32_job, win32_AssignProcessToJobObject
    if win32_job is None and sys.platform == "win32":
        import ctypes
        try:
            from ctypes.wintypes import BOOL, DWORD, HANDLE, LPVOID, LPCWSTR
            kernel32 = ctypes.WinDLL("kernel32")
            kernel32.CreateJobObjectW.argtypes = (LPVOID, LPCWSTR)
            kernel32.CreateJobObjectW.restype = HANDLE
            sijo_argtypes = (HANDLE, ctypes.c_int, LPVOID, DWORD)
            kernel32.SetInformationJobObject.argtypes = sijo_argtypes
            kernel32.SetInformationJobObject.restype = BOOL
            kernel32.AssignProcessToJobObject.argtypes = (HANDLE, HANDLE)
            kernel32.AssignProcessToJobObject.restype = BOOL
            kernel32.IsDebuggerPresent.argtypes = ()
            kernel32.IsDebuggerPresent.restype = BOOL
        except (AttributeError, TypeError, ImportError):
            kernel32 = None
        job = kernel32.CreateJobObjectW(None, None) if kernel32 else None
        job = subprocess.Handle(job) if job else job
        if job:
            from ctypes.wintypes import DWORD, LARGE_INTEGER, ULARGE_INTEGER

            class JOBOBJECT_BASIC_LIMIT_INFORMATION(ctypes.Structure):
                _fields_ = [
                    ("PerProcessUserTimeLimit", LARGE_INTEGER),
                    ("PerJobUserTimeLimit", LARGE_INTEGER),
                    ("LimitFlags", DWORD),
                    ("MinimumWorkingSetSize", ctypes.c_size_t),
                    ("MaximumWorkingSetSize", ctypes.c_size_t),
                    ("ActiveProcessLimit", DWORD),
                    ("Affinity", ctypes.c_size_t),
                    ("PriorityClass", DWORD),
                    ("SchedulingClass", DWORD),
                ]

            class IO_COUNTERS(ctypes.Structure):
                _fields_ = [
                    ("ReadOperationCount", ULARGE_INTEGER),
                    ("WriteOperationCount", ULARGE_INTEGER),
                    ("OtherOperationCount", ULARGE_INTEGER),
                    ("ReadTransferCount", ULARGE_INTEGER),
                    ("WriteTransferCount", ULARGE_INTEGER),
                    ("OtherTransferCount", ULARGE_INTEGER),
                ]

            class JOBOBJECT_EXTENDED_LIMIT_INFORMATION(ctypes.Structure):
                _fields_ = [
                    ("BasicLimitInformation",
                     JOBOBJECT_BASIC_LIMIT_INFORMATION),
                    ("IoInfo", IO_COUNTERS),
                    ("ProcessMemoryLimit", ctypes.c_size_t),
                    ("JobMemoryLimit", ctypes.c_size_t),
                    ("PeakProcessMemoryUsed", ctypes.c_size_t),
                    ("PeakJobMemoryUsed", ctypes.c_size_t),
                ]

            debug = kernel32.IsDebuggerPresent()

            # Defined in <WinNT.h>; also available here:
            # https://docs.microsoft.com/en-us/windows/win32/api/jobapi2/nf-jobapi2-setinformationjobobject
            JobObjectExtendedLimitInformation = 9
            JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800
            JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION = 0x00000400
            JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000
            buf = JOBOBJECT_EXTENDED_LIMIT_INFORMATION()
            buf.BasicLimitInformation.LimitFlags = (
                (0 if debug else JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE)
                | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION
                | JOB_OBJECT_LIMIT_BREAKAWAY_OK)
            infoclass = JobObjectExtendedLimitInformation
            if not kernel32.SetInformationJobObject(
                    job, infoclass, ctypes.byref(buf), ctypes.sizeof(buf)):
                job = None
        win32_AssignProcessToJobObject = (kernel32.AssignProcessToJobObject
                                          if kernel32 is not None else False)
        win32_job = job if job else False
    return bool(win32_job)
예제 #5
0
        def _execute_child(self, *args_tuple):
            if sys.hexversion < 0x02070600:  # prior to 2.7.6
                (args, executable, preexec_fn, close_fds, cwd, env,
                 universal_newlines, input_startupinfo, creationflags, shell,
                 p2cread, p2cwrite, c2pread, c2pwrite, errread,
                 errwrite) = args_tuple
                to_close = None
            elif sys.hexversion > 0x03040000:  # 3.4.0 and later
                (args, executable, preexec_fn, close_fds, pass_fds, cwd, env,
                 input_startupinfo, creationflags, shell, p2cread, p2cwrite,
                 c2pread, c2pwrite, errread, errwrite, restore_signals,
                 start_new_session) = args_tuple
                to_close = set()
                to_close.add(p2cread)
                if p2cwrite is not None:
                    to_close.add(p2cwrite)
                to_close.add(c2pwrite)
                if c2pread is not None:
                    to_close.add(c2pread)
                to_close.add(errwrite)
                if errread is not None:
                    to_close.add(errread)
            else:  # 2.7.6 and later
                (args, executable, preexec_fn, close_fds, cwd, env,
                 universal_newlines, input_startupinfo, creationflags, shell,
                 to_close, p2cread, p2cwrite, c2pread, c2pwrite, errread,
                 errwrite) = args_tuple

            if shell:
                return super(ProcThreadAttributeHandleListPopen,
                             self)._execute_child(*args_tuple)

            close_fds = self.__really_close_fds

            if not isinstance(args, basestring):
                args = subprocess.list2cmdline(args)

            if _winprocess_ctypes.CAN_USE_EXTENDED_STARTUPINFO:
                attribute_list_data = ()
                startupinfoex = _winprocess_ctypes.STARTUPINFOEX()
                startupinfo = startupinfoex.StartupInfo
                startupinfo.cb = _winprocess_ctypes.sizeof(
                    _winprocess_ctypes.STARTUPINFOEX)
                startupinfo_argument = startupinfoex
            else:
                startupinfo = _winprocess_ctypes.STARTUPINFO()
                startupinfo_argument = startupinfo

            if input_startupinfo is not None:
                startupinfo.dwFlags = input_startupinfo.dwFlags
                startupinfo.hStdInput = input_startupinfo.hStdInput
                startupinfo.hStdOutput = input_startupinfo.hStdOutput
                startupinfo.hStdError = input_startupinfo.hStdError
                startupinfo.wShowWindow = input_startupinfo.wShowWindow

            inherit_handles = 0 if close_fds else 1

            if None not in (p2cread, c2pwrite, errwrite):
                if close_fds:
                    HandleArray = _winprocess_ctypes.HANDLE * 3
                    # PY2COMPAT new_int doesn't seem to know how to convert file handles to int.
                    # So we use the "native_int" instead.
                    handles_to_inherit = HandleArray(native_int(p2cread),
                                                     native_int(c2pwrite),
                                                     native_int(errwrite))

                    attribute_list_data = (
                        (_winprocess_ctypes.PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
                         handles_to_inherit), )
                    inherit_handles = 1

                startupinfo.dwFlags |= _winprocess_ctypes.STARTF_USESTDHANDLES
                # PY2COMPAT new_int doesn't seem to know how to convert file handles to int.
                # So we use the "native_int" instead.
                startupinfo.hStdInput = native_int(p2cread)
                startupinfo.hStdOutput = native_int(c2pwrite)
                startupinfo.hStdError = native_int(errwrite)

            if _winprocess_ctypes.CAN_USE_EXTENDED_STARTUPINFO:
                attribute_list = _winprocess_ctypes.ProcThreadAttributeList(
                    attribute_list_data)
                startupinfoex.lpAttributeList = attribute_list.value
                creationflags |= _winprocess_ctypes.EXTENDED_STARTUPINFO_PRESENT

            def _close_in_parent(fd):
                fd.Close()
                if to_close:
                    to_close.remove(fd)

            # create the process
            try:
                hp, ht, pid, tid = _winprocess_ctypes.ExtendedCreateProcess(
                    executable,
                    args,
                    None,
                    None,  # No special security
                    inherit_handles,  #Inherit handles
                    creationflags,
                    _winprocess_ctypes.EnvironmentBlock(env) if env else None,
                    cwd,
                    startupinfo_argument)
            finally:
                # Child is launched. Close the parent's copy of those pipe
                # handles that only the child should have open.  You need
                # to make sure that no handles to the write end of the
                # output pipe are maintained in this process or else the
                # pipe will not close when the child process exits and the
                # ReadFile will hang.
                if p2cread is not None:
                    _close_in_parent(p2cread)
                if c2pwrite is not None:
                    _close_in_parent(c2pwrite)
                if errwrite is not None:
                    _close_in_parent(errwrite)

            self._child_created = True
            self._handle = subprocess.Handle(hp) if hasattr(
                subprocess, 'Handle') else hp
            self._thread = ht
            self.pid = pid
            self.tid = tid

            ht.Close()