76 def __init__(self, helper_path, env):
77
78
79
80
81
82
83
84
85
86 cmd_in_r, cmd_in_w = os.pipe()
87 cmd_out_r, cmd_out_w = os.pipe()
88
89 if sys.platform == "win32":
90 cmd_in_handle = msvcrt.get_osfhandle(cmd_in_r)
91 cmd_out_handle = msvcrt.get_osfhandle(cmd_out_w)
92 os.set_handle_inheritable(cmd_in_handle, True)
93 os.set_handle_inheritable(cmd_out_handle, True)
94 cmd_in_arg = f"--cmdInFd={cmd_in_handle:x}"
95 cmd_out_arg = f"--cmdOutFd={cmd_out_handle:x}"
96
97
98
99
100 popen_kwargs = {"close_fds": False}
101 else:
102 cmd_in_arg = f"--cmdInFd=P{cmd_in_r:x}"
103 cmd_out_arg = f"--cmdOutFd=P{cmd_out_w:x}"
104 popen_kwargs = {"close_fds": True, "pass_fds": (cmd_in_r, cmd_out_w)}
105
106 self.proc = subprocess.Popen(
107 [helper_path, cmd_in_arg, cmd_out_arg],
108 stdin=subprocess.DEVNULL,
109 stdout=None,
110 stderr=None,
111 env=env,
112 **popen_kwargs,
113 )
114 os.close(cmd_in_r)
115 os.close(cmd_out_w)
116 self._in = os.fdopen(cmd_in_w, "w", buffering=1)
117 self._out = os.fdopen(cmd_out_r, "r")
118 self._lines = queue.Queue()
119 self._reader = threading.Thread(target=self._read_loop, daemon=True)
120 self._reader.start()
121 self._next_id = 0
122