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