Eryk Sun <eryk...@gmail.com> added the comment:

I'm not fond of the way reduction.DupHandle() expects the receiving process to 
steal the duplicated handle. I'd prefer using the resource_sharer module, like 
reduction.DupFd() does in POSIX. Except spawning is a special case, for which 
reduction.DupHandle() can take advantage of the duplicate_for_child() method of 
the popen_spawn_win32.Popen instance.

With the resource sharer, the handle still needs to be duplicated in the 
sending process. But an important difference is the resource_sharer.stop() 
method, which at least allows closing any handles that no longer need to be 
shared.

---

Proposed Changes (untested)

resource_sharer.py:

    class DupHandle(object):
        '''Wrapper for a handle that can be used at any time.'''
        def __init__(self, handle):
            dh = reduction.duplicate(handle)
            def send(conn, pid):
                reduction.send_handle(conn, dh, pid)
            def close():
                _winapi.CloseHandle(dh)
            self._id = _resource_sharer.register(send, close)

        def detach(self):
            '''Get the handle. This should only be called once.'''
            with _resource_sharer.get_connection(self._id) as conn:
                return reduction.recv_handle(conn)


reduction.py:

    def send_handle(conn, handle, destination_pid):
        '''Send a handle over a local connection.'''
        proc = _winapi.OpenProcess(_winapi.PROCESS_DUP_HANDLE, False,
            destination_pid)
        try:
            dh = duplicate(handle, proc)
            conn.send(dh)
        finally:
            _winapi.CloseHandle(proc)

    def recv_handle(conn):
        '''Receive a handle over a local connection.'''
        return conn.recv()

    class _DupHandle:
        def __init__(self, handle):
            self.handle = handle
        def detach(self):
            return self.handle

    def DupHandle(handle):
        '''Return a wrapper for a handle.'''
        popen_obj = context.get_spawning_popen()
        if popen_obj is not None:
            return _DupHandle(popen_obj.duplicate_for_child(handle))
        from . import resource_sharer
        return resource_sharer.DupHandle(handle)


connection.py:

    def reduce_pipe_connection(conn):
        dh = reduction.DupHandle(conn.fileno())
        return rebuild_pipe_connection, (dh, conn.readable, conn.writable)

    def rebuild_pipe_connection(dh, readable, writable):
        return PipeConnection(dh.detach(), readable, writable)

    reduction.register(PipeConnection, reduce_pipe_connection)

----------
components: +Library (Lib)
nosy: +eryksun
versions: +Python 3.10

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue42968>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to