blob: 5e7cd795895d65456dc8a372421c8cc29c046bcd [file] [log] [blame]
Yury Selivanovb0b0e622014-02-18 22:27:48 -05001"""Selector and proactor event loops for Windows."""
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07002
Victor Stinner4271dfd2017-11-28 15:19:56 +01003import _overlapped
Victor Stinnerf2e17682014-01-31 16:25:24 +01004import _winapi
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07005import errno
Victor Stinnerf2e17682014-01-31 16:25:24 +01006import math
Andrew Svetlova19fb3c2018-02-25 19:32:14 +03007import msvcrt
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07008import socket
Victor Stinnerf2e17682014-01-31 16:25:24 +01009import struct
Victor Stinnerb1e45732019-01-15 11:48:00 +010010import time
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070011import weakref
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070012
Guido van Rossum0eaa5ac2013-11-04 15:50:46 -080013from . import events
Guido van Rossum59691282013-10-30 14:52:03 -070014from . import base_subprocess
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070015from . import futures
Andrew Svetlov0baa72f2018-09-11 10:13:04 -070016from . import exceptions
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070017from . import proactor_events
18from . import selector_events
19from . import tasks
20from . import windows_utils
Victor Stinnerf951d282014-06-29 00:46:45 +020021from .log import logger
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070022
23
Yury Selivanov6370f342017-12-10 18:36:12 -050024__all__ = (
25 'SelectorEventLoop', 'ProactorEventLoop', 'IocpProactor',
Yury Selivanov8f404292018-06-07 20:44:57 -040026 'DefaultEventLoopPolicy', 'WindowsSelectorEventLoopPolicy',
27 'WindowsProactorEventLoopPolicy',
Yury Selivanov6370f342017-12-10 18:36:12 -050028)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070029
30
31NULL = 0
32INFINITE = 0xffffffff
33ERROR_CONNECTION_REFUSED = 1225
34ERROR_CONNECTION_ABORTED = 1236
35
Victor Stinner7ffa2c52015-01-22 22:55:08 +010036# Initial delay in seconds for connect_pipe() before retrying to connect
37CONNECT_PIPE_INIT_DELAY = 0.001
38
39# Maximum delay in seconds for connect_pipe() before retrying to connect
40CONNECT_PIPE_MAX_DELAY = 0.100
41
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070042
43class _OverlappedFuture(futures.Future):
44 """Subclass of Future which represents an overlapped operation.
45
46 Cancelling it will immediately cancel the overlapped operation.
47 """
48
49 def __init__(self, ov, *, loop=None):
50 super().__init__(loop=loop)
Victor Stinnerfea6a102014-07-25 00:54:53 +020051 if self._source_traceback:
52 del self._source_traceback[-1]
Victor Stinner18a28dc2014-07-25 13:05:20 +020053 self._ov = ov
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070054
Victor Stinner313a9802014-07-29 12:58:23 +020055 def _repr_info(self):
56 info = super()._repr_info()
Victor Stinner18a28dc2014-07-25 13:05:20 +020057 if self._ov is not None:
58 state = 'pending' if self._ov.pending else 'completed'
Yury Selivanov6370f342017-12-10 18:36:12 -050059 info.insert(1, f'overlapped=<{state}, {self._ov.address:#x}>')
Victor Stinner313a9802014-07-29 12:58:23 +020060 return info
Victor Stinnere912e652014-07-12 03:11:53 +020061
Victor Stinner18a28dc2014-07-25 13:05:20 +020062 def _cancel_overlapped(self):
63 if self._ov is None:
64 return
65 try:
66 self._ov.cancel()
67 except OSError as exc:
68 context = {
69 'message': 'Cancelling an overlapped future failed',
70 'exception': exc,
71 'future': self,
72 }
73 if self._source_traceback:
74 context['source_traceback'] = self._source_traceback
75 self._loop.call_exception_handler(context)
76 self._ov = None
77
Chris Jerdonek1ce58412020-05-15 16:55:50 -070078 def cancel(self, msg=None):
Victor Stinner18a28dc2014-07-25 13:05:20 +020079 self._cancel_overlapped()
Chris Jerdonek1ce58412020-05-15 16:55:50 -070080 return super().cancel(msg=msg)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070081
Victor Stinner18a28dc2014-07-25 13:05:20 +020082 def set_exception(self, exception):
83 super().set_exception(exception)
84 self._cancel_overlapped()
85
Victor Stinner51e44ea2014-07-26 00:58:34 +020086 def set_result(self, result):
87 super().set_result(result)
88 self._ov = None
89
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070090
Victor Stinnerd0a28de2015-01-21 23:39:51 +010091class _BaseWaitHandleFuture(futures.Future):
Guido van Rossum90fb9142013-10-30 14:44:05 -070092 """Subclass of Future which represents a wait handle."""
93
Victor Stinnerd0a28de2015-01-21 23:39:51 +010094 def __init__(self, ov, handle, wait_handle, *, loop=None):
Guido van Rossum90fb9142013-10-30 14:44:05 -070095 super().__init__(loop=loop)
Victor Stinner313a9802014-07-29 12:58:23 +020096 if self._source_traceback:
97 del self._source_traceback[-1]
Victor Stinnerd0a28de2015-01-21 23:39:51 +010098 # Keep a reference to the Overlapped object to keep it alive until the
99 # wait is unregistered
Victor Stinner313a9802014-07-29 12:58:23 +0200100 self._ov = ov
Victor Stinner18a28dc2014-07-25 13:05:20 +0200101 self._handle = handle
Guido van Rossum90fb9142013-10-30 14:44:05 -0700102 self._wait_handle = wait_handle
103
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100104 # Should we call UnregisterWaitEx() if the wait completes
105 # or is cancelled?
106 self._registered = True
107
Victor Stinner18a28dc2014-07-25 13:05:20 +0200108 def _poll(self):
109 # non-blocking wait: use a timeout of 0 millisecond
110 return (_winapi.WaitForSingleObject(self._handle, 0) ==
111 _winapi.WAIT_OBJECT_0)
112
Victor Stinner313a9802014-07-29 12:58:23 +0200113 def _repr_info(self):
114 info = super()._repr_info()
Yury Selivanov6370f342017-12-10 18:36:12 -0500115 info.append(f'handle={self._handle:#x}')
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100116 if self._handle is not None:
Victor Stinner313a9802014-07-29 12:58:23 +0200117 state = 'signaled' if self._poll() else 'waiting'
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100118 info.append(state)
119 if self._wait_handle is not None:
Yury Selivanov6370f342017-12-10 18:36:12 -0500120 info.append(f'wait_handle={self._wait_handle:#x}')
Victor Stinner313a9802014-07-29 12:58:23 +0200121 return info
Victor Stinner18a28dc2014-07-25 13:05:20 +0200122
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100123 def _unregister_wait_cb(self, fut):
124 # The wait was unregistered: it's not safe to destroy the Overlapped
125 # object
126 self._ov = None
127
Victor Stinner313a9802014-07-29 12:58:23 +0200128 def _unregister_wait(self):
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100129 if not self._registered:
Victor Stinnerfea6a102014-07-25 00:54:53 +0200130 return
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100131 self._registered = False
132
Victor Stinner24dfa3c2015-01-26 22:30:28 +0100133 wait_handle = self._wait_handle
134 self._wait_handle = None
Guido van Rossum90fb9142013-10-30 14:44:05 -0700135 try:
Victor Stinner24dfa3c2015-01-26 22:30:28 +0100136 _overlapped.UnregisterWait(wait_handle)
Victor Stinnerb2614752014-08-25 23:20:52 +0200137 except OSError as exc:
Victor Stinner24dfa3c2015-01-26 22:30:28 +0100138 if exc.winerror != _overlapped.ERROR_IO_PENDING:
Victor Stinnerb2614752014-08-25 23:20:52 +0200139 context = {
140 'message': 'Failed to unregister the wait handle',
141 'exception': exc,
142 'future': self,
143 }
144 if self._source_traceback:
145 context['source_traceback'] = self._source_traceback
146 self._loop.call_exception_handler(context)
Victor Stinner24dfa3c2015-01-26 22:30:28 +0100147 return
148 # ERROR_IO_PENDING means that the unregister is pending
149
150 self._unregister_wait_cb(None)
Victor Stinnerfea6a102014-07-25 00:54:53 +0200151
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700152 def cancel(self, msg=None):
Victor Stinner313a9802014-07-29 12:58:23 +0200153 self._unregister_wait()
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700154 return super().cancel(msg=msg)
Victor Stinner313a9802014-07-29 12:58:23 +0200155
156 def set_exception(self, exception):
Victor Stinner313a9802014-07-29 12:58:23 +0200157 self._unregister_wait()
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100158 super().set_exception(exception)
Victor Stinner313a9802014-07-29 12:58:23 +0200159
160 def set_result(self, result):
Victor Stinner313a9802014-07-29 12:58:23 +0200161 self._unregister_wait()
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100162 super().set_result(result)
163
164
165class _WaitCancelFuture(_BaseWaitHandleFuture):
166 """Subclass of Future which represents a wait for the cancellation of a
167 _WaitHandleFuture using an event.
168 """
169
170 def __init__(self, ov, event, wait_handle, *, loop=None):
171 super().__init__(ov, event, wait_handle, loop=loop)
172
173 self._done_callback = None
174
Victor Stinner1ca93922015-01-22 00:17:54 +0100175 def cancel(self):
176 raise RuntimeError("_WaitCancelFuture must not be cancelled")
177
INADA Naokia8363622016-10-21 12:30:15 +0900178 def set_result(self, result):
179 super().set_result(result)
180 if self._done_callback is not None:
181 self._done_callback(self)
182
183 def set_exception(self, exception):
184 super().set_exception(exception)
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100185 if self._done_callback is not None:
186 self._done_callback(self)
187
188
189class _WaitHandleFuture(_BaseWaitHandleFuture):
190 def __init__(self, ov, handle, wait_handle, proactor, *, loop=None):
191 super().__init__(ov, handle, wait_handle, loop=loop)
192 self._proactor = proactor
193 self._unregister_proactor = True
194 self._event = _overlapped.CreateEvent(None, True, False, None)
195 self._event_fut = None
196
197 def _unregister_wait_cb(self, fut):
198 if self._event is not None:
199 _winapi.CloseHandle(self._event)
200 self._event = None
201 self._event_fut = None
202
203 # If the wait was cancelled, the wait may never be signalled, so
204 # it's required to unregister it. Otherwise, IocpProactor.close() will
205 # wait forever for an event which will never come.
206 #
207 # If the IocpProactor already received the event, it's safe to call
208 # _unregister() because we kept a reference to the Overlapped object
Martin Panter6245cb32016-04-15 02:14:19 +0000209 # which is used as a unique key.
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100210 self._proactor._unregister(self._ov)
211 self._proactor = None
212
213 super()._unregister_wait_cb(fut)
214
215 def _unregister_wait(self):
216 if not self._registered:
217 return
218 self._registered = False
219
Victor Stinner24dfa3c2015-01-26 22:30:28 +0100220 wait_handle = self._wait_handle
221 self._wait_handle = None
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100222 try:
Victor Stinner24dfa3c2015-01-26 22:30:28 +0100223 _overlapped.UnregisterWaitEx(wait_handle, self._event)
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100224 except OSError as exc:
Victor Stinner24dfa3c2015-01-26 22:30:28 +0100225 if exc.winerror != _overlapped.ERROR_IO_PENDING:
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100226 context = {
227 'message': 'Failed to unregister the wait handle',
228 'exception': exc,
229 'future': self,
230 }
231 if self._source_traceback:
232 context['source_traceback'] = self._source_traceback
233 self._loop.call_exception_handler(context)
Victor Stinner24dfa3c2015-01-26 22:30:28 +0100234 return
235 # ERROR_IO_PENDING is not an error, the wait was unregistered
236
237 self._event_fut = self._proactor._wait_cancel(self._event,
238 self._unregister_wait_cb)
Guido van Rossum90fb9142013-10-30 14:44:05 -0700239
240
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700241class PipeServer(object):
242 """Class representing a pipe server.
243
244 This is much like a bound, listening socket.
245 """
246 def __init__(self, address):
247 self._address = address
248 self._free_instances = weakref.WeakSet()
Victor Stinnerb2614752014-08-25 23:20:52 +0200249 # initialize the pipe attribute before calling _server_pipe_handle()
250 # because this function can raise an exception and the destructor calls
251 # the close() method
252 self._pipe = None
253 self._accept_pipe_future = None
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700254 self._pipe = self._server_pipe_handle(True)
255
256 def _get_unconnected_pipe(self):
257 # Create new instance and return previous one. This ensures
258 # that (until the server is closed) there is always at least
259 # one pipe handle for address. Therefore if a client attempt
260 # to connect it will not fail with FileNotFoundError.
261 tmp, self._pipe = self._pipe, self._server_pipe_handle(False)
262 return tmp
263
264 def _server_pipe_handle(self, first):
265 # Return a wrapper for a new pipe handle.
Victor Stinnera19b7b32015-01-26 15:03:20 +0100266 if self.closed():
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700267 return None
268 flags = _winapi.PIPE_ACCESS_DUPLEX | _winapi.FILE_FLAG_OVERLAPPED
269 if first:
270 flags |= _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE
271 h = _winapi.CreateNamedPipe(
272 self._address, flags,
273 _winapi.PIPE_TYPE_MESSAGE | _winapi.PIPE_READMODE_MESSAGE |
274 _winapi.PIPE_WAIT,
275 _winapi.PIPE_UNLIMITED_INSTANCES,
276 windows_utils.BUFSIZE, windows_utils.BUFSIZE,
277 _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL)
278 pipe = windows_utils.PipeHandle(h)
279 self._free_instances.add(pipe)
280 return pipe
281
Victor Stinnera19b7b32015-01-26 15:03:20 +0100282 def closed(self):
283 return (self._address is None)
284
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700285 def close(self):
Victor Stinnerb2614752014-08-25 23:20:52 +0200286 if self._accept_pipe_future is not None:
287 self._accept_pipe_future.cancel()
288 self._accept_pipe_future = None
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700289 # Close all instances which have not been connected to by a client.
290 if self._address is not None:
291 for pipe in self._free_instances:
292 pipe.close()
293 self._pipe = None
294 self._address = None
295 self._free_instances.clear()
296
297 __del__ = close
298
299
Guido van Rossum0eaa5ac2013-11-04 15:50:46 -0800300class _WindowsSelectorEventLoop(selector_events.BaseSelectorEventLoop):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700301 """Windows version of selector event loop."""
302
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700303
304class ProactorEventLoop(proactor_events.BaseProactorEventLoop):
305 """Windows version of proactor event loop using IOCP."""
306
307 def __init__(self, proactor=None):
308 if proactor is None:
309 proactor = IocpProactor()
310 super().__init__(proactor)
311
Vladimir Matveevb5c8cfa2018-12-18 13:56:17 -0800312 def run_forever(self):
313 try:
314 assert self._self_reading_future is None
315 self.call_soon(self._loop_self_reading)
316 super().run_forever()
317 finally:
318 if self._self_reading_future is not None:
Vladimir Matveev67ba5472019-01-05 12:44:59 -0800319 ov = self._self_reading_future._ov
Vladimir Matveevb5c8cfa2018-12-18 13:56:17 -0800320 self._self_reading_future.cancel()
Ben Darnellea5a6362020-08-31 15:57:52 -0400321 # self_reading_future was just cancelled so if it hasn't been
322 # finished yet, it never will be (it's possible that it has
323 # already finished and its callback is waiting in the queue,
324 # where it could still happen if the event loop is restarted).
325 # Unregister it otherwise IocpProactor.close will wait for it
326 # forever
Vladimir Matveev67ba5472019-01-05 12:44:59 -0800327 if ov is not None:
328 self._proactor._unregister(ov)
Vladimir Matveevb5c8cfa2018-12-18 13:56:17 -0800329 self._self_reading_future = None
330
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200331 async def create_pipe_connection(self, protocol_factory, address):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700332 f = self._proactor.connect_pipe(address)
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200333 pipe = await f
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700334 protocol = protocol_factory()
335 trans = self._make_duplex_pipe_transport(pipe, protocol,
336 extra={'addr': address})
337 return trans, protocol
338
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200339 async def start_serving_pipe(self, protocol_factory, address):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700340 server = PipeServer(address)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700341
Victor Stinnerb2614752014-08-25 23:20:52 +0200342 def loop_accept_pipe(f=None):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700343 pipe = None
344 try:
345 if f:
346 pipe = f.result()
347 server._free_instances.discard(pipe)
Victor Stinnera19b7b32015-01-26 15:03:20 +0100348
349 if server.closed():
350 # A client connected before the server was closed:
351 # drop the client (close the pipe) and exit
352 pipe.close()
353 return
354
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700355 protocol = protocol_factory()
356 self._make_duplex_pipe_transport(
357 pipe, protocol, extra={'addr': address})
Victor Stinnera19b7b32015-01-26 15:03:20 +0100358
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700359 pipe = server._get_unconnected_pipe()
360 if pipe is None:
361 return
Victor Stinnera19b7b32015-01-26 15:03:20 +0100362
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700363 f = self._proactor.accept_pipe(pipe)
Yury Selivanovff827f02014-02-18 18:02:19 -0500364 except OSError as exc:
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700365 if pipe and pipe.fileno() != -1:
Yury Selivanovff827f02014-02-18 18:02:19 -0500366 self.call_exception_handler({
367 'message': 'Pipe accept failed',
368 'exception': exc,
369 'pipe': pipe,
370 })
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700371 pipe.close()
Victor Stinnerb2614752014-08-25 23:20:52 +0200372 elif self._debug:
373 logger.warning("Accept pipe failed on pipe %r",
374 pipe, exc_info=True)
Andrew Svetlov0baa72f2018-09-11 10:13:04 -0700375 except exceptions.CancelledError:
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700376 if pipe:
377 pipe.close()
378 else:
Victor Stinnerb2614752014-08-25 23:20:52 +0200379 server._accept_pipe_future = f
380 f.add_done_callback(loop_accept_pipe)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700381
Victor Stinnerb2614752014-08-25 23:20:52 +0200382 self.call_soon(loop_accept_pipe)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700383 return [server]
384
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200385 async def _make_subprocess_transport(self, protocol, args, shell,
386 stdin, stdout, stderr, bufsize,
387 extra=None, **kwargs):
Yury Selivanov7661db62016-05-16 15:38:39 -0400388 waiter = self.create_future()
Guido van Rossum59691282013-10-30 14:52:03 -0700389 transp = _WindowsSubprocessTransport(self, protocol, args, shell,
390 stdin, stdout, stderr, bufsize,
Victor Stinner47cd10d2015-01-30 00:05:19 +0100391 waiter=waiter, extra=extra,
392 **kwargs)
Victor Stinner4bf22e02015-01-15 14:24:22 +0100393 try:
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200394 await waiter
Yury Selivanov431b5402019-05-27 14:45:12 +0200395 except (SystemExit, KeyboardInterrupt):
396 raise
397 except BaseException:
Victor Stinner4bf22e02015-01-15 14:24:22 +0100398 transp.close()
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200399 await transp._wait()
400 raise
Victor Stinner4bf22e02015-01-15 14:24:22 +0100401
Guido van Rossum59691282013-10-30 14:52:03 -0700402 return transp
403
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700404
405class IocpProactor:
406 """Proactor implementation using IOCP."""
407
408 def __init__(self, concurrency=0xffffffff):
409 self._loop = None
410 self._results = []
411 self._iocp = _overlapped.CreateIoCompletionPort(
412 _overlapped.INVALID_HANDLE_VALUE, NULL, 0, concurrency)
413 self._cache = {}
414 self._registered = weakref.WeakSet()
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100415 self._unregistered = []
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700416 self._stopped_serving = weakref.WeakSet()
417
Victor Stinner9b076812019-01-10 11:23:26 +0100418 def _check_closed(self):
419 if self._iocp is None:
420 raise RuntimeError('IocpProactor is closed')
421
Victor Stinnerfea6a102014-07-25 00:54:53 +0200422 def __repr__(self):
Victor Stinner9b076812019-01-10 11:23:26 +0100423 info = ['overlapped#=%s' % len(self._cache),
424 'result#=%s' % len(self._results)]
425 if self._iocp is None:
426 info.append('closed')
427 return '<%s %s>' % (self.__class__.__name__, " ".join(info))
Victor Stinnerfea6a102014-07-25 00:54:53 +0200428
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700429 def set_loop(self, loop):
430 self._loop = loop
431
432 def select(self, timeout=None):
433 if not self._results:
434 self._poll(timeout)
435 tmp = self._results
436 self._results = []
437 return tmp
438
Victor Stinner41063d22015-01-26 22:30:49 +0100439 def _result(self, value):
Yury Selivanov7661db62016-05-16 15:38:39 -0400440 fut = self._loop.create_future()
Victor Stinner41063d22015-01-26 22:30:49 +0100441 fut.set_result(value)
442 return fut
443
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700444 def recv(self, conn, nbytes, flags=0):
445 self._register_with_iocp(conn)
446 ov = _overlapped.Overlapped(NULL)
Victor Stinner41063d22015-01-26 22:30:49 +0100447 try:
448 if isinstance(conn, socket.socket):
449 ov.WSARecv(conn.fileno(), nbytes, flags)
450 else:
451 ov.ReadFile(conn.fileno(), nbytes)
452 except BrokenPipeError:
453 return self._result(b'')
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700454
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100455 def finish_recv(trans, key, ov):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700456 try:
457 return ov.getresult()
458 except OSError as exc:
Andrew Svetlov7c684072018-01-27 21:22:47 +0200459 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
460 _overlapped.ERROR_OPERATION_ABORTED):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700461 raise ConnectionResetError(*exc.args)
462 else:
463 raise
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700464
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100465 return self._register(ov, conn, finish_recv)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700466
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200467 def recv_into(self, conn, buf, flags=0):
468 self._register_with_iocp(conn)
469 ov = _overlapped.Overlapped(NULL)
470 try:
471 if isinstance(conn, socket.socket):
472 ov.WSARecvInto(conn.fileno(), buf, flags)
473 else:
474 ov.ReadFileInto(conn.fileno(), buf)
475 except BrokenPipeError:
Victor Stinner602a9712020-08-04 02:40:10 +0200476 return self._result(0)
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200477
478 def finish_recv(trans, key, ov):
479 try:
480 return ov.getresult()
481 except OSError as exc:
Andrew Svetlov7c684072018-01-27 21:22:47 +0200482 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
483 _overlapped.ERROR_OPERATION_ABORTED):
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200484 raise ConnectionResetError(*exc.args)
485 else:
486 raise
487
488 return self._register(ov, conn, finish_recv)
489
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300490 def recvfrom(self, conn, nbytes, flags=0):
491 self._register_with_iocp(conn)
492 ov = _overlapped.Overlapped(NULL)
493 try:
494 ov.WSARecvFrom(conn.fileno(), nbytes, flags)
495 except BrokenPipeError:
496 return self._result((b'', None))
497
498 def finish_recv(trans, key, ov):
499 try:
500 return ov.getresult()
501 except OSError as exc:
502 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
503 _overlapped.ERROR_OPERATION_ABORTED):
504 raise ConnectionResetError(*exc.args)
505 else:
506 raise
507
508 return self._register(ov, conn, finish_recv)
509
510 def sendto(self, conn, buf, flags=0, addr=None):
511 self._register_with_iocp(conn)
512 ov = _overlapped.Overlapped(NULL)
513
514 ov.WSASendTo(conn.fileno(), buf, flags, addr)
515
516 def finish_send(trans, key, ov):
517 try:
518 return ov.getresult()
519 except OSError as exc:
520 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
521 _overlapped.ERROR_OPERATION_ABORTED):
522 raise ConnectionResetError(*exc.args)
523 else:
524 raise
525
526 return self._register(ov, conn, finish_send)
527
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700528 def send(self, conn, buf, flags=0):
529 self._register_with_iocp(conn)
530 ov = _overlapped.Overlapped(NULL)
531 if isinstance(conn, socket.socket):
532 ov.WSASend(conn.fileno(), buf, flags)
533 else:
534 ov.WriteFile(conn.fileno(), buf)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700535
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100536 def finish_send(trans, key, ov):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700537 try:
538 return ov.getresult()
539 except OSError as exc:
Andrew Svetlov7c684072018-01-27 21:22:47 +0200540 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
541 _overlapped.ERROR_OPERATION_ABORTED):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700542 raise ConnectionResetError(*exc.args)
543 else:
544 raise
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700545
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100546 return self._register(ov, conn, finish_send)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700547
548 def accept(self, listener):
549 self._register_with_iocp(listener)
550 conn = self._get_accept_socket(listener.family)
551 ov = _overlapped.Overlapped(NULL)
552 ov.AcceptEx(listener.fileno(), conn.fileno())
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700553
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700554 def finish_accept(trans, key, ov):
555 ov.getresult()
556 # Use SO_UPDATE_ACCEPT_CONTEXT so getsockname() etc work.
557 buf = struct.pack('@P', listener.fileno())
558 conn.setsockopt(socket.SOL_SOCKET,
559 _overlapped.SO_UPDATE_ACCEPT_CONTEXT, buf)
560 conn.settimeout(listener.gettimeout())
561 return conn, conn.getpeername()
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700562
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200563 async def accept_coro(future, conn):
Victor Stinner7de26462014-01-11 00:03:21 +0100564 # Coroutine closing the accept socket if the future is cancelled
565 try:
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200566 await future
Andrew Svetlov0baa72f2018-09-11 10:13:04 -0700567 except exceptions.CancelledError:
Victor Stinner7de26462014-01-11 00:03:21 +0100568 conn.close()
569 raise
570
571 future = self._register(ov, listener, finish_accept)
572 coro = accept_coro(future, conn)
Yury Selivanov59eb9a42015-05-11 14:48:38 -0400573 tasks.ensure_future(coro, loop=self._loop)
Victor Stinner7de26462014-01-11 00:03:21 +0100574 return future
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700575
576 def connect(self, conn, address):
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300577 if conn.type == socket.SOCK_DGRAM:
578 # WSAConnect will complete immediately for UDP sockets so we don't
579 # need to register any IOCP operation
580 _overlapped.WSAConnect(conn.fileno(), address)
581 fut = self._loop.create_future()
582 fut.set_result(None)
583 return fut
584
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700585 self._register_with_iocp(conn)
586 # The socket needs to be locally bound before we call ConnectEx().
587 try:
588 _overlapped.BindLocal(conn.fileno(), conn.family)
589 except OSError as e:
590 if e.winerror != errno.WSAEINVAL:
591 raise
592 # Probably already locally bound; check using getsockname().
593 if conn.getsockname()[1] == 0:
594 raise
595 ov = _overlapped.Overlapped(NULL)
596 ov.ConnectEx(conn.fileno(), address)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700597
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700598 def finish_connect(trans, key, ov):
599 ov.getresult()
600 # Use SO_UPDATE_CONNECT_CONTEXT so getsockname() etc work.
601 conn.setsockopt(socket.SOL_SOCKET,
602 _overlapped.SO_UPDATE_CONNECT_CONTEXT, 0)
603 return conn
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700604
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700605 return self._register(ov, conn, finish_connect)
606
Andrew Svetlova19fb3c2018-02-25 19:32:14 +0300607 def sendfile(self, sock, file, offset, count):
608 self._register_with_iocp(sock)
609 ov = _overlapped.Overlapped(NULL)
610 offset_low = offset & 0xffff_ffff
611 offset_high = (offset >> 32) & 0xffff_ffff
612 ov.TransmitFile(sock.fileno(),
613 msvcrt.get_osfhandle(file.fileno()),
614 offset_low, offset_high,
615 count, 0, 0)
616
617 def finish_sendfile(trans, key, ov):
618 try:
619 return ov.getresult()
620 except OSError as exc:
621 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
622 _overlapped.ERROR_OPERATION_ABORTED):
623 raise ConnectionResetError(*exc.args)
624 else:
625 raise
626 return self._register(ov, sock, finish_sendfile)
627
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700628 def accept_pipe(self, pipe):
629 self._register_with_iocp(pipe)
630 ov = _overlapped.Overlapped(NULL)
Victor Stinner2b77c542015-01-22 23:50:03 +0100631 connected = ov.ConnectNamedPipe(pipe.fileno())
632
633 if connected:
634 # ConnectNamePipe() failed with ERROR_PIPE_CONNECTED which means
635 # that the pipe is connected. There is no need to wait for the
636 # completion of the connection.
Victor Stinner41063d22015-01-26 22:30:49 +0100637 return self._result(pipe)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700638
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100639 def finish_accept_pipe(trans, key, ov):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700640 ov.getresult()
641 return pipe
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700642
Victor Stinner2b77c542015-01-22 23:50:03 +0100643 return self._register(ov, pipe, finish_accept_pipe)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700644
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200645 async def connect_pipe(self, address):
Victor Stinnere0fd1572015-01-26 15:04:03 +0100646 delay = CONNECT_PIPE_INIT_DELAY
647 while True:
Yury Selivanov6370f342017-12-10 18:36:12 -0500648 # Unfortunately there is no way to do an overlapped connect to
649 # a pipe. Call CreateFile() in a loop until it doesn't fail with
650 # ERROR_PIPE_BUSY.
Victor Stinnere0fd1572015-01-26 15:04:03 +0100651 try:
652 handle = _overlapped.ConnectPipe(address)
653 break
654 except OSError as exc:
655 if exc.winerror != _overlapped.ERROR_PIPE_BUSY:
656 raise
657
658 # ConnectPipe() failed with ERROR_PIPE_BUSY: retry later
659 delay = min(delay * 2, CONNECT_PIPE_MAX_DELAY)
Andrew Svetlov23b4b692019-05-27 22:56:22 +0300660 await tasks.sleep(delay)
Victor Stinnere0fd1572015-01-26 15:04:03 +0100661
662 return windows_utils.PipeHandle(handle)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700663
Guido van Rossum90fb9142013-10-30 14:44:05 -0700664 def wait_for_handle(self, handle, timeout=None):
Victor Stinner4d825b42014-12-19 17:10:44 +0100665 """Wait for a handle.
666
667 Return a Future object. The result of the future is True if the wait
668 completed, or False if the wait did not complete (on timeout).
669 """
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100670 return self._wait_for_handle(handle, timeout, False)
671
672 def _wait_cancel(self, event, done_callback):
673 fut = self._wait_for_handle(event, None, True)
674 # add_done_callback() cannot be used because the wait may only complete
675 # in IocpProactor.close(), while the event loop is not running.
676 fut._done_callback = done_callback
677 return fut
678
679 def _wait_for_handle(self, handle, timeout, _is_cancel):
Victor Stinner9b076812019-01-10 11:23:26 +0100680 self._check_closed()
681
Guido van Rossum90fb9142013-10-30 14:44:05 -0700682 if timeout is None:
683 ms = _winapi.INFINITE
684 else:
Victor Stinnerf2e17682014-01-31 16:25:24 +0100685 # RegisterWaitForSingleObject() has a resolution of 1 millisecond,
686 # round away from zero to wait *at least* timeout seconds.
687 ms = math.ceil(timeout * 1e3)
Guido van Rossum90fb9142013-10-30 14:44:05 -0700688
689 # We only create ov so we can use ov.address as a key for the cache.
690 ov = _overlapped.Overlapped(NULL)
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100691 wait_handle = _overlapped.RegisterWaitWithQueue(
Guido van Rossum90fb9142013-10-30 14:44:05 -0700692 handle, self._iocp, ov.address, ms)
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100693 if _is_cancel:
694 f = _WaitCancelFuture(ov, handle, wait_handle, loop=self._loop)
695 else:
696 f = _WaitHandleFuture(ov, handle, wait_handle, self,
697 loop=self._loop)
Victor Stinner313a9802014-07-29 12:58:23 +0200698 if f._source_traceback:
699 del f._source_traceback[-1]
Guido van Rossum90fb9142013-10-30 14:44:05 -0700700
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100701 def finish_wait_for_handle(trans, key, ov):
Richard Oudkerk71196e72013-11-24 17:50:40 +0000702 # Note that this second wait means that we should only use
703 # this with handles types where a successful wait has no
704 # effect. So events or processes are all right, but locks
705 # or semaphores are not. Also note if the handle is
706 # signalled and then quickly reset, then we may return
707 # False even though we have not timed out.
Victor Stinner313a9802014-07-29 12:58:23 +0200708 return f._poll()
Guido van Rossum90fb9142013-10-30 14:44:05 -0700709
Victor Stinner313a9802014-07-29 12:58:23 +0200710 self._cache[ov.address] = (f, ov, 0, finish_wait_for_handle)
Guido van Rossum90fb9142013-10-30 14:44:05 -0700711 return f
712
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700713 def _register_with_iocp(self, obj):
714 # To get notifications of finished ops on this objects sent to the
715 # completion port, were must register the handle.
716 if obj not in self._registered:
717 self._registered.add(obj)
718 _overlapped.CreateIoCompletionPort(obj.fileno(), self._iocp, 0, 0)
719 # XXX We could also use SetFileCompletionNotificationModes()
720 # to avoid sending notifications to completion port of ops
721 # that succeed immediately.
722
Victor Stinner2b77c542015-01-22 23:50:03 +0100723 def _register(self, ov, obj, callback):
Victor Stinner9b076812019-01-10 11:23:26 +0100724 self._check_closed()
725
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700726 # Return a future which will be set with the result of the
727 # operation when it completes. The future's value is actually
728 # the value returned by callback().
729 f = _OverlappedFuture(ov, loop=self._loop)
Victor Stinner313a9802014-07-29 12:58:23 +0200730 if f._source_traceback:
731 del f._source_traceback[-1]
Victor Stinner2b77c542015-01-22 23:50:03 +0100732 if not ov.pending:
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700733 # The operation has completed, so no need to postpone the
734 # work. We cannot take this short cut if we need the
735 # NumberOfBytes, CompletionKey values returned by
736 # PostQueuedCompletionStatus().
737 try:
738 value = callback(None, None, ov)
739 except OSError as e:
740 f.set_exception(e)
741 else:
742 f.set_result(value)
Victor Stinner42d3bde2014-07-28 00:18:43 +0200743 # Even if GetOverlappedResult() was called, we have to wait for the
744 # notification of the completion in GetQueuedCompletionStatus().
745 # Register the overlapped operation to keep a reference to the
746 # OVERLAPPED object, otherwise the memory is freed and Windows may
747 # read uninitialized memory.
Victor Stinner2b77c542015-01-22 23:50:03 +0100748
749 # Register the overlapped operation for later. Note that
750 # we only store obj to prevent it from being garbage
751 # collected too early.
752 self._cache[ov.address] = (f, ov, obj, callback)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700753 return f
754
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100755 def _unregister(self, ov):
756 """Unregister an overlapped object.
757
758 Call this method when its future has been cancelled. The event can
759 already be signalled (pending in the proactor event queue). It is also
760 safe if the event is never signalled (because it was cancelled).
761 """
Victor Stinner9b076812019-01-10 11:23:26 +0100762 self._check_closed()
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100763 self._unregistered.append(ov)
764
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700765 def _get_accept_socket(self, family):
766 s = socket.socket(family)
767 s.settimeout(0)
768 return s
769
770 def _poll(self, timeout=None):
771 if timeout is None:
772 ms = INFINITE
773 elif timeout < 0:
774 raise ValueError("negative timeout")
775 else:
Victor Stinnerf2e17682014-01-31 16:25:24 +0100776 # GetQueuedCompletionStatus() has a resolution of 1 millisecond,
777 # round away from zero to wait *at least* timeout seconds.
778 ms = math.ceil(timeout * 1e3)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700779 if ms >= INFINITE:
780 raise ValueError("timeout too big")
Victor Stinner313a9802014-07-29 12:58:23 +0200781
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700782 while True:
783 status = _overlapped.GetQueuedCompletionStatus(self._iocp, ms)
784 if status is None:
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100785 break
Victor Stinner313a9802014-07-29 12:58:23 +0200786 ms = 0
787
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700788 err, transferred, key, address = status
789 try:
790 f, ov, obj, callback = self._cache.pop(address)
791 except KeyError:
Victor Stinner42d3bde2014-07-28 00:18:43 +0200792 if self._loop.get_debug():
793 self._loop.call_exception_handler({
794 'message': ('GetQueuedCompletionStatus() returned an '
795 'unexpected event'),
796 'status': ('err=%s transferred=%s key=%#x address=%#x'
797 % (err, transferred, key, address)),
798 })
799
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700800 # key is either zero, or it is used to return a pipe
801 # handle which should be closed to avoid a leak.
802 if key not in (0, _overlapped.INVALID_HANDLE_VALUE):
803 _winapi.CloseHandle(key)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700804 continue
Victor Stinner51e44ea2014-07-26 00:58:34 +0200805
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700806 if obj in self._stopped_serving:
807 f.cancel()
Victor Stinner42d3bde2014-07-28 00:18:43 +0200808 # Don't call the callback if _register() already read the result or
809 # if the overlapped has been cancelled
810 elif not f.done():
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700811 try:
812 value = callback(transferred, key, ov)
813 except OSError as e:
814 f.set_exception(e)
815 self._results.append(f)
816 else:
817 f.set_result(value)
818 self._results.append(f)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700819
Andrew Svetlov7a6706b2017-12-13 17:50:16 +0200820 # Remove unregistered futures
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100821 for ov in self._unregistered:
822 self._cache.pop(ov.address, None)
823 self._unregistered.clear()
824
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700825 def _stop_serving(self, obj):
826 # obj is a socket or pipe handle. It will be closed in
827 # BaseProactorEventLoop._stop_serving() which will make any
828 # pending operations fail quickly.
829 self._stopped_serving.add(obj)
830
831 def close(self):
Victor Stinner9b076812019-01-10 11:23:26 +0100832 if self._iocp is None:
833 # already closed
834 return
835
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700836 # Cancel remaining registered operations.
Victor Stinnerfea6a102014-07-25 00:54:53 +0200837 for address, (fut, ov, obj, callback) in list(self._cache.items()):
Victor Stinner3d2256f2015-01-26 11:02:59 +0100838 if fut.cancelled():
Victor Stinner752aba72015-01-22 22:47:13 +0100839 # Nothing to do with cancelled futures
840 pass
Victor Stinner1ca93922015-01-22 00:17:54 +0100841 elif isinstance(fut, _WaitCancelFuture):
842 # _WaitCancelFuture must not be cancelled
843 pass
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700844 else:
845 try:
Victor Stinnerfea6a102014-07-25 00:54:53 +0200846 fut.cancel()
847 except OSError as exc:
848 if self._loop is not None:
849 context = {
850 'message': 'Cancelling a future failed',
851 'exception': exc,
852 'future': fut,
853 }
854 if fut._source_traceback:
855 context['source_traceback'] = fut._source_traceback
856 self._loop.call_exception_handler(context)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700857
Victor Stinnerb1e45732019-01-15 11:48:00 +0100858 # Wait until all cancelled overlapped complete: don't exit with running
859 # overlapped to prevent a crash. Display progress every second if the
860 # loop is still running.
861 msg_update = 1.0
862 start_time = time.monotonic()
863 next_msg = start_time + msg_update
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700864 while self._cache:
Victor Stinnerb1e45732019-01-15 11:48:00 +0100865 if next_msg <= time.monotonic():
Victor Stinnerb91140f2019-01-15 12:13:48 +0100866 logger.debug('%r is running after closing for %.1f seconds',
867 self, time.monotonic() - start_time)
Victor Stinnerb1e45732019-01-15 11:48:00 +0100868 next_msg = time.monotonic() + msg_update
869
870 # handle a few events, or timeout
871 self._poll(msg_update)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700872
873 self._results = []
Victor Stinner9b076812019-01-10 11:23:26 +0100874
875 _winapi.CloseHandle(self._iocp)
876 self._iocp = None
Guido van Rossum59691282013-10-30 14:52:03 -0700877
Victor Stinnerfea6a102014-07-25 00:54:53 +0200878 def __del__(self):
879 self.close()
880
Guido van Rossum59691282013-10-30 14:52:03 -0700881
882class _WindowsSubprocessTransport(base_subprocess.BaseSubprocessTransport):
883
884 def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
885 self._proc = windows_utils.Popen(
886 args, shell=shell, stdin=stdin, stdout=stdout, stderr=stderr,
887 bufsize=bufsize, **kwargs)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700888
Guido van Rossum59691282013-10-30 14:52:03 -0700889 def callback(f):
890 returncode = self._proc.poll()
891 self._process_exited(returncode)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700892
Guido van Rossum59691282013-10-30 14:52:03 -0700893 f = self._loop._proactor.wait_for_handle(int(self._proc._handle))
894 f.add_done_callback(callback)
Guido van Rossum0eaa5ac2013-11-04 15:50:46 -0800895
896
897SelectorEventLoop = _WindowsSelectorEventLoop
898
899
Yury Selivanov8f404292018-06-07 20:44:57 -0400900class WindowsSelectorEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
Guido van Rossum0eaa5ac2013-11-04 15:50:46 -0800901 _loop_factory = SelectorEventLoop
902
903
Yury Selivanov8f404292018-06-07 20:44:57 -0400904class WindowsProactorEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
905 _loop_factory = ProactorEventLoop
906
907
Victor Stinner6ea29c52018-09-25 08:27:08 -0700908DefaultEventLoopPolicy = WindowsProactorEventLoopPolicy