def test_pipe_overlapped(self): h1, h2 = windows_utils.pipe(overlapped=(True, True)) try: ov1 = _overlapped.Overlapped() self.assertFalse(ov1.pending) self.assertEqual(ov1.error, 0) ov1.ReadFile(h1, 100) self.assertTrue(ov1.pending) self.assertEqual(ov1.error, _winapi.ERROR_IO_PENDING) ERROR_IO_INCOMPLETE = 996 try: ov1.getresult() except OSError as e: self.assertEqual(e.winerror, ERROR_IO_INCOMPLETE) else: raise RuntimeError('expected ERROR_IO_INCOMPLETE') ov2 = _overlapped.Overlapped() self.assertFalse(ov2.pending) self.assertEqual(ov2.error, 0) ov2.WriteFile(h2, b'hello') self.assertIn(ov2.error, {0, _winapi.ERROR_IO_PENDING}) res = _winapi.WaitForMultipleObjects([ov2.event], False, 100) self.assertEqual(res, _winapi.WAIT_OBJECT_0) self.assertFalse(ov1.pending) self.assertEqual(ov1.error, ERROR_IO_INCOMPLETE) self.assertFalse(ov2.pending) self.assertIn(ov2.error, {0, _winapi.ERROR_IO_PENDING}) self.assertEqual(ov1.getresult(), b'hello') finally: _winapi.CloseHandle(h1) _winapi.CloseHandle(h2)
def Pipe(duplex=True, rnonblock=False, wnonblock=False): # noqa ''' Returns pair of connection objects at either end of a pipe ''' address = arbitrary_address('AF_PIPE') if duplex: openmode = _winapi.PIPE_ACCESS_DUPLEX access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE obsize, ibsize = BUFSIZE, BUFSIZE else: openmode = _winapi.PIPE_ACCESS_INBOUND access = _winapi.GENERIC_WRITE obsize, ibsize = 0, BUFSIZE h1 = _winapi.CreateNamedPipe( address, openmode | _winapi.FILE_FLAG_OVERLAPPED | _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE, _winapi.PIPE_TYPE_MESSAGE | _winapi.PIPE_READMODE_MESSAGE | _winapi.PIPE_WAIT, 1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL) h2 = _winapi.CreateFile(address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING, _winapi.FILE_FLAG_OVERLAPPED, _winapi.NULL) _winapi.SetNamedPipeHandleState(h2, _winapi.PIPE_READMODE_MESSAGE, None, None) overlapped = _winapi.ConnectNamedPipe(h1, overlapped=True) _, err = overlapped.GetOverlappedResult(True) assert err == 0 c1 = PipeConnection(duplicate(h1, inheritable=True), writable=duplex) c2 = PipeConnection(duplicate(h2, inheritable=True), readable=duplex) _winapi.CloseHandle(h1) _winapi.CloseHandle(h2) return c1, c2
def _get_handles(self, stdin, stdout, stderr): if stdin is None and stdout is None and stderr is None: return (-1, -1, -1, -1, -1, -1) (p2cread, p2cwrite) = (-1, -1) (c2pread, c2pwrite) = (-1, -1) (errread, errwrite) = (-1, -1) if stdin is None: p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE) (p2cread, _) = _winapi.CreatePipe(None, 0) p2cread = Handle(p2cread) _winapi.CloseHandle(_) elif stdin == PIPE: (p2cread, p2cwrite) = _winapi.CreatePipe(None, 0) (p2cread, p2cwrite) = (Handle(p2cread), Handle(p2cwrite)) elif stdin == DEVNULL: p2cread = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdin, int): p2cread = msvcrt.get_osfhandle(stdin) else: p2cread = msvcrt.get_osfhandle(stdin.fileno()) p2cread = self._make_inheritable(p2cread) if stdout is None: c2pwrite = _winapi.GetStdHandle(_winapi.STD_OUTPUT_HANDLE) (_, c2pwrite) = _winapi.CreatePipe(None, 0) c2pwrite = Handle(c2pwrite) _winapi.CloseHandle(_) elif stdout == PIPE: (c2pread, c2pwrite) = _winapi.CreatePipe(None, 0) (c2pread, c2pwrite) = (Handle(c2pread), Handle(c2pwrite)) elif stdout == DEVNULL: c2pwrite = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdout, int): c2pwrite = msvcrt.get_osfhandle(stdout) else: c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) c2pwrite = self._make_inheritable(c2pwrite) if stderr is None: errwrite = _winapi.GetStdHandle(_winapi.STD_ERROR_HANDLE) (_, errwrite) = _winapi.CreatePipe(None, 0) errwrite = Handle(errwrite) _winapi.CloseHandle(_) elif stderr == PIPE: (errread, errwrite) = _winapi.CreatePipe(None, 0) (errread, errwrite) = (Handle(errread), Handle(errwrite)) elif stderr == STDOUT: errwrite = c2pwrite elif stderr == DEVNULL: errwrite = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stderr, int): errwrite = msvcrt.get_osfhandle(stderr) else: errwrite = msvcrt.get_osfhandle(stderr.fileno()) errwrite = self._make_inheritable(errwrite) return (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite)
def __init__(self, process_obj): prep_data = spawn.get_preparation_data(process_obj._name) # read end of pipe will be duplicated by the child process # -- see spawn_main() in spawn.py. # # bpo-33929: Previously, the read end of pipe was "stolen" by the child # process, but it leaked a handle if the child process had been # terminated before it could steal the handle from the parent process. rhandle, whandle = _winapi.CreatePipe(None, 0) wfd = msvcrt.open_osfhandle(whandle, 0) cmd = spawn.get_command_line(parent_pid=os.getpid(), pipe_handle=rhandle) cmd = ' '.join('"%s"' % x for x in cmd) python_exe = spawn.get_executable() # bpo-35797: When running in a venv, we bypass the redirect # executor and launch our base Python. if WINENV and _path_eq(python_exe, sys.executable): python_exe = sys._base_executable env = os.environ.copy() env["__PYVENV_LAUNCHER__"] = sys.executable else: env = os.environ.copy() env['Y_PYTHON_ENTRY_POINT'] = ':main' with open(wfd, 'wb', closefd=True) as to_child: # start process try: hp, ht, pid, tid = _winapi.CreateProcess( python_exe, cmd, None, None, False, 0, env, None, None) _winapi.CloseHandle(ht) except: _winapi.CloseHandle(rhandle) raise # set attributes of self self.pid = pid self.returncode = None self._handle = hp self.sentinel = int(hp) self.finalizer = util.Finalize(self, _close_handles, (self.sentinel, int(rhandle))) # send information to child set_spawning_popen(self) try: reduction.dump(prep_data, to_child) reduction.dump(process_obj, to_child) finally: set_spawning_popen(None)
def cmdl(ctx, components, config, n_environments, exploit, show_ui): """Run RELAAX components. \b COMPONENTS: all - run environments and servers (default) environment - run environment servers - run rlx-server, parameter-server, metrics-server and wsproxy (if specified in config yaml) rlx-server - run rlx-server parameter-server - run parameter-server metrics-server - run metrics-server wsproxy - run websockets proxy \b For example: - run environment, rlx-server, parameter-server, metrics-server, and wsproxy $relaax run all - run rlx-server, parameter-server, metrics-server, and wsproxy $relaax run servers """ ctx.setup_logger(format='%(asctime)s %(name)s\t\t | %(message)s') # Disable TF warnings os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' os.environ["COMSPEC"] = "powershell.exe" # Execute command if sys.platform == 'win32': honcho.manager.KILL_WAIT = 120 honcho.process.Popen = PopenPatched import _winapi import ctypes firstRun = False mutex = ctypes.windll.kernel32.CreateMutexA(None, False, "RELAAX_WINDOWS_MUTEX") if _winapi.GetLastError() == 0: firstRun = True if firstRun: os.system("start powershell " + ' '.join(sys.argv)) time.sleep(5) _winapi.CloseHandle(mutex) else: _winapi.CloseHandle(mutex) honcho.process.Popen = PopenPatched CmdlRun(ctx, set(components), config.name, n_environments, exploit, show_ui).run_components() else: CmdlRun(ctx, set(components), config.name, n_environments, exploit, show_ui).run_components()
def __init__(self, name=None, create=False, size=0): if not size >= 0: raise ValueError("'size' must be a positive integer") if create: self._flags = _O_CREX | os.O_RDWR if name is None and not self._flags & os.O_EXCL: raise ValueError("'name' can only be None if create=True") # Windows Named Shared Memory if create: while True: temp_name = _make_filename() if name is None else name # Create and reserve shared memory block with this name # until it can be attached to by mmap. h_map = _winapi.CreateFileMapping( _winapi.INVALID_HANDLE_VALUE, _winapi.NULL, _winapi.PAGE_READWRITE, (size >> 32) & 0xFFFFFFFF, size & 0xFFFFFFFF, temp_name) try: last_error_code = _winapi.GetLastError() if last_error_code == _winapi.ERROR_ALREADY_EXISTS: if name is not None: raise FileExistsError( errno.EEXIST, os.strerror(errno.EEXIST), name, _winapi.ERROR_ALREADY_EXISTS) else: continue self._mmap = mmap.mmap(-1, size, tagname=temp_name) finally: _winapi.CloseHandle(h_map) self._name = temp_name break else: self._name = name # Dynamically determine the existing named shared memory # block's size which is likely a multiple of mmap.PAGESIZE. h_map = _winapi.OpenFileMapping(_winapi.FILE_MAP_READ, False, name) try: p_buf = _winapi.MapViewOfFile(h_map, _winapi.FILE_MAP_READ, 0, 0, 0) finally: _winapi.CloseHandle(h_map) size = _winapi.VirtualQuerySize(p_buf) self._mmap = mmap.mmap(-1, size, tagname=name) self._size = size self._buf = memoryview(self._mmap)
def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, unused_restore_signals, unused_start_new_session): if not isinstance(args, str): args = list2cmdline(args) if startupinfo is None: startupinfo = STARTUPINFO() if -1 not in (p2cread, c2pwrite, errwrite): startupinfo.hStdInput = p2cread startupinfo.hStdOutput = c2pwrite startupinfo.hStdError = errwrite if shell: startupinfo.wShowWindow = _winapi.SW_HIDE comspec = os.environ.get('COMSPEC', 'cmd.exe') args = '{} /c "{}"'.format(comspec, args) if _winapi.GetVersion() >= 2147483648 or os.path.basename(comspec).lower() == 'command.com': w9xpopen = self._find_w9xpopen() args = '"%s" %s' % (w9xpopen, args) creationflags |= _winapi.CREATE_NEW_CONSOLE try: (hp, ht, pid, tid) = _winapi.CreateProcess(executable, args, None, None, int(not close_fds), creationflags, env, cwd, startupinfo) except pywintypes.error as e: raise WindowsError(*e.args) finally: if p2cread != -1: p2cread.Close() if c2pwrite != -1: c2pwrite.Close() if errwrite != -1: errwrite.Close() if hasattr(self, '_devnull'): os.close(self._devnull) self._child_created = True self._handle = Handle(hp) self.pid = pid _winapi.CloseHandle(ht)
def _poll(self, timeout=None): if timeout is None: ms = INFINITE elif timeout < 0: raise ValueError("negative timeout") else: ms = int(timeout * 1000 + 0.5) if ms >= INFINITE: raise ValueError("timeout too big") while True: status = _overlapped.GetQueuedCompletionStatus(self._iocp, ms) if status is None: return err, transferred, key, address = status try: f, ov, obj, callback = self._cache.pop(address) except KeyError: # key is either zero, or it is used to return a pipe # handle which should be closed to avoid a leak. if key not in (0, _overlapped.INVALID_HANDLE_VALUE): _winapi.CloseHandle(key) ms = 0 continue if obj in self._stopped_serving: f.cancel() elif not f.cancelled(): try: value = callback(transferred, key, ov) except OSError as e: f.set_exception(e) self._results.append(f) else: f.set_result(value) self._results.append(f) ms = 0
def close(self): # Cancel remaining registered operations. for address, (fut, ov, obj, callback) in list(self._cache.items()): if obj is None: # The operation was started with connect_pipe() which # queues a task to Windows' thread pool. This cannot # be cancelled, so just forget it. del self._cache[address] # FIXME: Tulip issue 196: remove this case, it should not happen elif fut.done() and not fut.cancelled(): del self._cache[address] else: try: fut.cancel() except OSError as exc: if self._loop is not None: context = { 'message': 'Cancelling a future failed', 'exception': exc, 'future': fut, } if fut._source_traceback: context['source_traceback'] = fut._source_traceback self._loop.call_exception_handler(context) while self._cache: if not self._poll(1): logger.debug('taking long time to close proactor') self._results = [] if self._iocp is not None: _winapi.CloseHandle(self._iocp) self._iocp = None
def test_pipe_handle(self): h, _ = windows_utils.pipe(overlapped=(True, True)) _winapi.CloseHandle(_) p = windows_utils.PipeHandle(h) self.assertEqual(p.fileno(), h) self.assertEqual(p.handle, h) with warnings.catch_warnings(): warnings.filterwarnings('ignore', '', ResourceWarning) del p support.gc_collect() try: _winapi.CloseHandle(h) except OSError as e: self.assertEqual(e.winerror, 6) else: raise RuntimeError('expected ERROR_INVALID_HANDLE')
def _pid_alive(pid): """Check if the process with this PID is alive or not. Args: pid: The pid to check. Returns: This returns false if the process is dead. Otherwise, it returns true. """ no_such_process = errno.EINVAL if sys.platform == "win32" else errno.ESRCH alive = True try: if sys.platform == "win32": SYNCHRONIZE = 0x00100000 # access mask defined in <winnt.h> handle = _winapi.OpenProcess(SYNCHRONIZE, False, pid) try: alive = (_winapi.WaitForSingleObject(handle, 0) != _winapi.WAIT_OBJECT_0) finally: _winapi.CloseHandle(handle) else: os.kill(pid, 0) except OSError as ex: if ex.errno != no_such_process: raise alive = False return alive
def spawn_main(pipe_handle, parent_pid=None, tracker_fd=None): ''' Run code specified by data received over pipe ''' assert is_forking(sys.argv), "Not forking" if sys.platform == 'win32': import msvcrt import _winapi if parent_pid is not None: source_process = _winapi.OpenProcess(_winapi.PROCESS_DUP_HANDLE, False, parent_pid) else: source_process = None try: new_handle = reduction.duplicate(pipe_handle, source_process=source_process) finally: if source_process is not None: _winapi.CloseHandle(source_process) fd = msvcrt.open_osfhandle(new_handle, os.O_RDONLY) else: from . import resource_tracker resource_tracker._resource_tracker._fd = tracker_fd fd = pipe_handle exitcode = _main(fd) sys.exit(exitcode)
def close(self): # Cancel remaining registered operations. for address, (fut, ov, obj, callback) in list(self._cache.items()): if fut.cancelled(): # Nothing to do with cancelled futures pass elif isinstance(fut, _WaitCancelFuture): # _WaitCancelFuture must not be cancelled pass else: try: fut.cancel() except OSError as exc: if self._loop is not None: context = { 'message': 'Cancelling a future failed', 'exception': exc, 'future': fut, } if fut._source_traceback: context['source_traceback'] = fut._source_traceback self._loop.call_exception_handler(context) while self._cache: if not self._poll(1): logger.debug('taking long time to close proactor') self._results = [] if self._iocp is not None: _winapi.CloseHandle(self._iocp) self._iocp = None
def test_pipe_handle(self): h, _ = windows_utils.pipe(overlapped=(True, True)) _winapi.CloseHandle(_) p = windows_utils.PipeHandle(h) self.assertEqual(p.fileno(), h) self.assertEqual(p.handle, h) # check garbage collection of p closes handle del p support.gc_collect() try: _winapi.CloseHandle(h) except OSError as e: self.assertEqual(e.winerror, 6) # ERROR_INVALID_HANDLE else: raise RuntimeError('expected ERROR_INVALID_HANDLE')
def __enter__(self) -> 'IPCServer': if sys.platform == 'win32': # NOTE: It is theoretically possible that this will hang forever if the # client never connects, though this can be "solved" by killing the server try: ov = _winapi.ConnectNamedPipe(self.connection, overlapped=True) # TODO: remove once typeshed supports Literal types assert isinstance(ov, _winapi.Overlapped) except OSError as e: # Don't raise if the client already exists, or the client already connected if e.winerror not in (_winapi.ERROR_PIPE_CONNECTED, _winapi.ERROR_NO_DATA): raise else: try: timeout = int(self.timeout * 1000) if self.timeout else _winapi.INFINITE res = _winapi.WaitForSingleObject(ov.event, timeout) assert res == _winapi.WAIT_OBJECT_0 except BaseException: ov.cancel() _winapi.CloseHandle(self.connection) raise _, err = ov.GetOverlappedResult(True) assert err == 0 else: try: self.connection, _ = self.sock.accept() except socket.timeout as e: raise IPCException('The socket timed out') from e return self
async def accept(self): self._handle_queue.append(self._new_handle()) handle = self._handle_queue.pop(0) try: ov = _winapi.ConnectNamedPipe(handle, overlapped=True) except OSError as e: if e.winerror != _winapi.ERROR_NO_DATA: raise # ERROR_NO_DATA can occur if a client has already connected, # written data and then disconnected -- see Issue 14725. else: try: # res = _winapi.WaitForMultipleObjects( # [ov.event], False, INFINITE) await _wait_for_ov(ov) except: ov.cancel() _winapi.CloseHandle(handle) raise finally: _, err = ov.GetOverlappedResult(True) assert err == 0 if self._wrap_ssl: return AsyncSslPipeConnection(handle, server_side=True) else: return AsyncPipeConnection(handle, server_side=True)
def __init__(self, args, stdin=None, stdout=None, stderr=None, **kwds): stdin_rfd = stdout_wfd = stderr_wfd = None stdin_wh = stdout_rh = stderr_rh = None if stdin == PIPE: stdin_rh, stdin_wh = pipe(overlapped=(False, True)) stdin_rfd = msvcrt.open_osfhandle(stdin_rh, os.O_RDONLY) if stdout == PIPE: stdout_rh, stdout_wh = pipe(overlapped=(True, False)) stdout_wfd = msvcrt.open_osfhandle(stdout_wh, 0) if stderr == PIPE: stderr_rh, stderr_wh = pipe(overlapped=(True, False)) stderr_wfd = msvcrt.open_osfhandle(stderr_wh, 0) try: super().__init__(args, bufsize=0, universal_newlines=False, stdin=stdin_rfd, stdout=stdout_wfd, stderr=stderr_wfd, **kwds) except: for h in (stdin_wh, stdout_rh, stderr_rh): _winapi.CloseHandle(h) raise else: if stdin_wh is not None: self.stdin = PipeHandle(stdin_wh) if stdout_rh is not None: self.stdout = PipeHandle(stdout_rh) if stderr_rh is not None: self.stderr = PipeHandle(stderr_rh) finally: if stdin == PIPE: os.close(stdin_rfd) if stdout == PIPE: os.close(stdout_wfd) if stderr == PIPE: os.close(stderr_wfd)
def __init__(self, process_obj): cmd = ' '.join('"%s"' % x for x in get_command_line()) prep_data = get_preparation_data(process_obj._name) # create pipe for communication with child rfd, wfd = os.pipe() # get handle for read end of the pipe and make it inheritable rhandle = duplicate(msvcrt.get_osfhandle(rfd), inheritable=True) os.close(rfd) with open(wfd, 'wb', closefd=True) as to_child: # start process try: hp, ht, pid, tid = _winapi.CreateProcess( _python_exe, cmd + (' %s' % rhandle), None, None, 1, 0, None, None, None) _winapi.CloseHandle(ht) finally: close(rhandle) # set attributes of self self.pid = pid self.returncode = None self._handle = hp self.sentinel = int(hp) # send information to child Popen._tls.process_handle = int(hp) try: dump(prep_data, to_child, HIGHEST_PROTOCOL) dump(process_obj, to_child, HIGHEST_PROTOCOL) finally: del Popen._tls.process_handle
def kill(self): if sys.platform == 'win32': import _winapi handle = _winapi.OpenProcess(1, False, self._process.pid) _winapi.TerminateProcess(handle, -1) _winapi.CloseHandle(handle) else: os.kill(self.process.pid, signal.SIGKILL)
def _unregister_wait_cb(self, fut): if self._event is not None: _winapi.CloseHandle(self._event) self._event = None self._event_fut = None self._proactor._unregister(self._ov) self._proactor = None super()._unregister_wait_cb(fut)
def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE): """Like os.pipe() but with overlapped support and using handles not fds.""" address = tempfile.mktemp(prefix=r'\\.\pipe\python-pipe-{:d}-{:d}-'.format( os.getpid(), next(_mmap_counter))) if duplex: openmode = _winapi.PIPE_ACCESS_DUPLEX access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE obsize, ibsize = bufsize, bufsize else: openmode = _winapi.PIPE_ACCESS_INBOUND access = _winapi.GENERIC_WRITE obsize, ibsize = 0, bufsize openmode |= _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE if overlapped[0]: openmode |= _winapi.FILE_FLAG_OVERLAPPED if overlapped[1]: flags_and_attribs = _winapi.FILE_FLAG_OVERLAPPED else: flags_and_attribs = 0 h1 = h2 = None try: h1 = _winapi.CreateNamedPipe(address, openmode, _winapi.PIPE_WAIT, 1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL) h2 = _winapi.CreateFile(address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING, flags_and_attribs, _winapi.NULL) ov = _winapi.ConnectNamedPipe(h1, overlapped=True) ov.GetOverlappedResult(True) return h1, h2 except: if h1 is not None: _winapi.CloseHandle(h1) if h2 is not None: _winapi.CloseHandle(h2) raise
def _poll(self, timeout=None): if timeout is None: ms = INFINITE elif timeout < 0: raise ValueError("negative timeout") else: # GetQueuedCompletionStatus() has a resolution of 1 millisecond, # round away from zero to wait *at least* timeout seconds. ms = math.ceil(timeout * 1e3) if ms >= INFINITE: raise ValueError("timeout too big") while True: status = _overlapped.GetQueuedCompletionStatus(self._iocp, ms) if status is None: break ms = 0 err, transferred, key, address = status try: f, ov, obj, callback = self._cache.pop(address) except KeyError: if self._loop.get_debug(): self._loop.call_exception_handler({ 'message': ('GetQueuedCompletionStatus() returned an ' 'unexpected event'), 'status': ('err=%s transferred=%s key=%#x address=%#x' % (err, transferred, key, address)), }) # key is either zero, or it is used to return a pipe # handle which should be closed to avoid a leak. if key not in (0, _overlapped.INVALID_HANDLE_VALUE): _winapi.CloseHandle(key) continue if obj in self._stopped_serving: f.cancel() # Don't call the callback if _register() already read the result or # if the overlapped has been cancelled elif not f.done(): try: value = callback(transferred, key, ov) except OSError as e: f.set_exception(e) self._results.append(f) else: f.set_result(value) self._results.append(f) # Remove unregisted futures for ov in self._unregistered: self._cache.pop(ov.address, None) self._unregistered.clear()
def steal_handle(source_pid, handle): """Steal a handle from process identified by source_pid.""" source_process_handle = _winapi.OpenProcess(_winapi. PROCESS_DUP_HANDLE, False, source_pid) try: return _winapi.DuplicateHandle(source_process_handle, handle, _winapi.GetCurrentProcess(), 0, False, _winapi. DUPLICATE_SAME_ACCESS | _winapi.DUPLICATE_CLOSE_SOURCE) finally: _winapi.CloseHandle(source_process_handle)
def __init__(self, handle, access, pid=None): if pid is None: pid = os.getpid() proc = _winapi.OpenProcess(_winapi.PROCESS_DUP_HANDLE, False, pid) try: self._handle = _winapi.DuplicateHandle(_winapi. GetCurrentProcess(), handle, proc, access, False, 0) finally: _winapi.CloseHandle(proc) self._access = access self._pid = pid
def __init__(self, process_obj): prep_data = spawn.get_preparation_data(process_obj._name) # read end of pipe will be duplicated by the child process # -- see spawn_main() in spawn.py. # # bpo-33929: Previously, the read end of pipe was "stolen" by the child # process, but it leaked a handle if the child process had been # terminated before it could steal the handle from the parent process. rhandle, whandle = _winapi.CreatePipe(None, 0) wfd = msvcrt.open_osfhandle(whandle, 0) cmd = spawn.get_command_line(parent_pid=os.getpid(), pipe_handle=rhandle) cmd = ' '.join('"%s"' % x for x in cmd) with open(wfd, 'wb', closefd=True) as to_child: # start process try: hp, ht, pid, tid = _winapi.CreateProcess( spawn.get_executable(), cmd, None, None, False, 0, None, None, None) _winapi.CloseHandle(ht) except: _winapi.CloseHandle(rhandle) raise # set attributes of self self.pid = pid self.returncode = None self._handle = hp self.sentinel = int(hp) self.finalizer = util.Finalize(self, _close_handles, (self.sentinel, int(rhandle))) # send information to child set_spawning_popen(self) try: reduction.dump(prep_data, to_child) reduction.dump(process_obj, to_child) finally: set_spawning_popen(None)
def detach(self): """Get the handle. This should only be called once.""" if self._pid == os.getpid(): return self._handle proc = _winapi.OpenProcess(_winapi.PROCESS_DUP_HANDLE, False, self._pid) try: return _winapi.DuplicateHandle(proc, self._handle, _winapi. GetCurrentProcess(), self._access, False, _winapi. DUPLICATE_CLOSE_SOURCE) finally: _winapi.CloseHandle(proc)
def detach(self): # retrieve handle from process which currently owns it if self._pid == os.getpid(): return self._handle proc = _winapi.OpenProcess(_winapi.PROCESS_DUP_HANDLE, False, self._pid) try: return _winapi.DuplicateHandle( proc, self._handle, _winapi.GetCurrentProcess(), self._access, False, _winapi.DUPLICATE_CLOSE_SOURCE) finally: _winapi.CloseHandle(proc)
def __init__(self, handle, access, pid=None): if pid is None: # We just duplicate the handle in the current process and # let the receiving process steal the handle. pid = os.getpid() proc = _winapi.OpenProcess(_winapi.PROCESS_DUP_HANDLE, False, pid) try: self._handle = _winapi.DuplicateHandle( _winapi.GetCurrentProcess(), handle, proc, access, False, 0) finally: _winapi.CloseHandle(proc) self._access = access self._pid = pid
def detach(self): '''Get the handle. This should only be called once.''' # retrieve handle from process which currently owns it if self._pid == os.getpid(): # The handle has already been duplicated for this process. return self._handle # We must steal the handle from the process whose pid is self._pid. proc = _winapi.OpenProcess(_winapi.PROCESS_DUP_HANDLE, False, self._pid) try: return _winapi.DuplicateHandle( proc, self._handle, _winapi.GetCurrentProcess(), self._access, False, _winapi.DUPLICATE_CLOSE_SOURCE) finally: _winapi.CloseHandle(proc)
def __init__(self, process_obj): prep_data = spawn.get_preparation_data(process_obj._name) # read end of pipe will be "stolen" by the child process # -- see spawn_main() in spawn.py. rhandle, whandle = _winapi.CreatePipe(None, 0) wfd = msvcrt.open_osfhandle(whandle, 0) cmd = spawn.get_command_line(parent_pid=os.getpid(), pipe_handle=rhandle) cmd = ' '.join('"%s"' % x for x in cmd) with open(wfd, 'wb', closefd=True) as to_child: # start process try: hp, ht, pid, tid = _winapi.CreateProcess( spawn.get_executable(), cmd, None, None, False, 0, None, None, None) _winapi.CloseHandle(ht) except: _winapi.CloseHandle(rhandle) raise # set attributes of self self.pid = pid self.returncode = None self._handle = hp self.sentinel = int(hp) util.Finalize(self, _winapi.CloseHandle, (self.sentinel, )) # send information to child popen.set_spawning_popen(self) try: reduction.dump(prep_data, to_child) reduction.dump(process_obj, to_child) finally: popen.set_spawning_popen(None)