blob: a6759b78bd801fab79bc94e9cfa4ea441653ba56 [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()
Vladimir Matveev67ba5472019-01-05 12:44:59 -0800321 # self_reading_future was just cancelled so it will never be signalled
322 # Unregister it otherwise IocpProactor.close will wait for it forever
323 if ov is not None:
324 self._proactor._unregister(ov)
Vladimir Matveevb5c8cfa2018-12-18 13:56:17 -0800325 self._self_reading_future = None
326
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200327 async def create_pipe_connection(self, protocol_factory, address):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700328 f = self._proactor.connect_pipe(address)
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200329 pipe = await f
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700330 protocol = protocol_factory()
331 trans = self._make_duplex_pipe_transport(pipe, protocol,
332 extra={'addr': address})
333 return trans, protocol
334
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200335 async def start_serving_pipe(self, protocol_factory, address):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700336 server = PipeServer(address)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700337
Victor Stinnerb2614752014-08-25 23:20:52 +0200338 def loop_accept_pipe(f=None):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700339 pipe = None
340 try:
341 if f:
342 pipe = f.result()
343 server._free_instances.discard(pipe)
Victor Stinnera19b7b32015-01-26 15:03:20 +0100344
345 if server.closed():
346 # A client connected before the server was closed:
347 # drop the client (close the pipe) and exit
348 pipe.close()
349 return
350
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700351 protocol = protocol_factory()
352 self._make_duplex_pipe_transport(
353 pipe, protocol, extra={'addr': address})
Victor Stinnera19b7b32015-01-26 15:03:20 +0100354
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700355 pipe = server._get_unconnected_pipe()
356 if pipe is None:
357 return
Victor Stinnera19b7b32015-01-26 15:03:20 +0100358
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700359 f = self._proactor.accept_pipe(pipe)
Yury Selivanovff827f02014-02-18 18:02:19 -0500360 except OSError as exc:
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700361 if pipe and pipe.fileno() != -1:
Yury Selivanovff827f02014-02-18 18:02:19 -0500362 self.call_exception_handler({
363 'message': 'Pipe accept failed',
364 'exception': exc,
365 'pipe': pipe,
366 })
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700367 pipe.close()
Victor Stinnerb2614752014-08-25 23:20:52 +0200368 elif self._debug:
369 logger.warning("Accept pipe failed on pipe %r",
370 pipe, exc_info=True)
Andrew Svetlov0baa72f2018-09-11 10:13:04 -0700371 except exceptions.CancelledError:
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700372 if pipe:
373 pipe.close()
374 else:
Victor Stinnerb2614752014-08-25 23:20:52 +0200375 server._accept_pipe_future = f
376 f.add_done_callback(loop_accept_pipe)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700377
Victor Stinnerb2614752014-08-25 23:20:52 +0200378 self.call_soon(loop_accept_pipe)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700379 return [server]
380
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200381 async def _make_subprocess_transport(self, protocol, args, shell,
382 stdin, stdout, stderr, bufsize,
383 extra=None, **kwargs):
Yury Selivanov7661db62016-05-16 15:38:39 -0400384 waiter = self.create_future()
Guido van Rossum59691282013-10-30 14:52:03 -0700385 transp = _WindowsSubprocessTransport(self, protocol, args, shell,
386 stdin, stdout, stderr, bufsize,
Victor Stinner47cd10d2015-01-30 00:05:19 +0100387 waiter=waiter, extra=extra,
388 **kwargs)
Victor Stinner4bf22e02015-01-15 14:24:22 +0100389 try:
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200390 await waiter
Yury Selivanov431b5402019-05-27 14:45:12 +0200391 except (SystemExit, KeyboardInterrupt):
392 raise
393 except BaseException:
Victor Stinner4bf22e02015-01-15 14:24:22 +0100394 transp.close()
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200395 await transp._wait()
396 raise
Victor Stinner4bf22e02015-01-15 14:24:22 +0100397
Guido van Rossum59691282013-10-30 14:52:03 -0700398 return transp
399
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700400
401class IocpProactor:
402 """Proactor implementation using IOCP."""
403
404 def __init__(self, concurrency=0xffffffff):
405 self._loop = None
406 self._results = []
407 self._iocp = _overlapped.CreateIoCompletionPort(
408 _overlapped.INVALID_HANDLE_VALUE, NULL, 0, concurrency)
409 self._cache = {}
410 self._registered = weakref.WeakSet()
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100411 self._unregistered = []
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700412 self._stopped_serving = weakref.WeakSet()
413
Victor Stinner9b076812019-01-10 11:23:26 +0100414 def _check_closed(self):
415 if self._iocp is None:
416 raise RuntimeError('IocpProactor is closed')
417
Victor Stinnerfea6a102014-07-25 00:54:53 +0200418 def __repr__(self):
Victor Stinner9b076812019-01-10 11:23:26 +0100419 info = ['overlapped#=%s' % len(self._cache),
420 'result#=%s' % len(self._results)]
421 if self._iocp is None:
422 info.append('closed')
423 return '<%s %s>' % (self.__class__.__name__, " ".join(info))
Victor Stinnerfea6a102014-07-25 00:54:53 +0200424
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700425 def set_loop(self, loop):
426 self._loop = loop
427
428 def select(self, timeout=None):
429 if not self._results:
430 self._poll(timeout)
431 tmp = self._results
432 self._results = []
433 return tmp
434
Victor Stinner41063d22015-01-26 22:30:49 +0100435 def _result(self, value):
Yury Selivanov7661db62016-05-16 15:38:39 -0400436 fut = self._loop.create_future()
Victor Stinner41063d22015-01-26 22:30:49 +0100437 fut.set_result(value)
438 return fut
439
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700440 def recv(self, conn, nbytes, flags=0):
441 self._register_with_iocp(conn)
442 ov = _overlapped.Overlapped(NULL)
Victor Stinner41063d22015-01-26 22:30:49 +0100443 try:
444 if isinstance(conn, socket.socket):
445 ov.WSARecv(conn.fileno(), nbytes, flags)
446 else:
447 ov.ReadFile(conn.fileno(), nbytes)
448 except BrokenPipeError:
449 return self._result(b'')
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700450
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100451 def finish_recv(trans, key, ov):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700452 try:
453 return ov.getresult()
454 except OSError as exc:
Andrew Svetlov7c684072018-01-27 21:22:47 +0200455 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
456 _overlapped.ERROR_OPERATION_ABORTED):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700457 raise ConnectionResetError(*exc.args)
458 else:
459 raise
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700460
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100461 return self._register(ov, conn, finish_recv)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700462
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200463 def recv_into(self, conn, buf, flags=0):
464 self._register_with_iocp(conn)
465 ov = _overlapped.Overlapped(NULL)
466 try:
467 if isinstance(conn, socket.socket):
468 ov.WSARecvInto(conn.fileno(), buf, flags)
469 else:
470 ov.ReadFileInto(conn.fileno(), buf)
471 except BrokenPipeError:
Miss Islington (bot)1d162292020-08-03 18:00:29 -0700472 return self._result(0)
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200473
474 def finish_recv(trans, key, ov):
475 try:
476 return ov.getresult()
477 except OSError as exc:
Andrew Svetlov7c684072018-01-27 21:22:47 +0200478 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
479 _overlapped.ERROR_OPERATION_ABORTED):
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200480 raise ConnectionResetError(*exc.args)
481 else:
482 raise
483
484 return self._register(ov, conn, finish_recv)
485
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300486 def recvfrom(self, conn, nbytes, flags=0):
487 self._register_with_iocp(conn)
488 ov = _overlapped.Overlapped(NULL)
489 try:
490 ov.WSARecvFrom(conn.fileno(), nbytes, flags)
491 except BrokenPipeError:
492 return self._result((b'', None))
493
494 def finish_recv(trans, key, ov):
495 try:
496 return ov.getresult()
497 except OSError as exc:
498 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
499 _overlapped.ERROR_OPERATION_ABORTED):
500 raise ConnectionResetError(*exc.args)
501 else:
502 raise
503
504 return self._register(ov, conn, finish_recv)
505
506 def sendto(self, conn, buf, flags=0, addr=None):
507 self._register_with_iocp(conn)
508 ov = _overlapped.Overlapped(NULL)
509
510 ov.WSASendTo(conn.fileno(), buf, flags, addr)
511
512 def finish_send(trans, key, ov):
513 try:
514 return ov.getresult()
515 except OSError as exc:
516 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
517 _overlapped.ERROR_OPERATION_ABORTED):
518 raise ConnectionResetError(*exc.args)
519 else:
520 raise
521
522 return self._register(ov, conn, finish_send)
523
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700524 def send(self, conn, buf, flags=0):
525 self._register_with_iocp(conn)
526 ov = _overlapped.Overlapped(NULL)
527 if isinstance(conn, socket.socket):
528 ov.WSASend(conn.fileno(), buf, flags)
529 else:
530 ov.WriteFile(conn.fileno(), buf)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700531
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100532 def finish_send(trans, key, ov):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700533 try:
534 return ov.getresult()
535 except OSError as exc:
Andrew Svetlov7c684072018-01-27 21:22:47 +0200536 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
537 _overlapped.ERROR_OPERATION_ABORTED):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700538 raise ConnectionResetError(*exc.args)
539 else:
540 raise
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700541
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100542 return self._register(ov, conn, finish_send)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700543
544 def accept(self, listener):
545 self._register_with_iocp(listener)
546 conn = self._get_accept_socket(listener.family)
547 ov = _overlapped.Overlapped(NULL)
548 ov.AcceptEx(listener.fileno(), conn.fileno())
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700549
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700550 def finish_accept(trans, key, ov):
551 ov.getresult()
552 # Use SO_UPDATE_ACCEPT_CONTEXT so getsockname() etc work.
553 buf = struct.pack('@P', listener.fileno())
554 conn.setsockopt(socket.SOL_SOCKET,
555 _overlapped.SO_UPDATE_ACCEPT_CONTEXT, buf)
556 conn.settimeout(listener.gettimeout())
557 return conn, conn.getpeername()
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700558
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200559 async def accept_coro(future, conn):
Victor Stinner7de26462014-01-11 00:03:21 +0100560 # Coroutine closing the accept socket if the future is cancelled
561 try:
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200562 await future
Andrew Svetlov0baa72f2018-09-11 10:13:04 -0700563 except exceptions.CancelledError:
Victor Stinner7de26462014-01-11 00:03:21 +0100564 conn.close()
565 raise
566
567 future = self._register(ov, listener, finish_accept)
568 coro = accept_coro(future, conn)
Yury Selivanov59eb9a42015-05-11 14:48:38 -0400569 tasks.ensure_future(coro, loop=self._loop)
Victor Stinner7de26462014-01-11 00:03:21 +0100570 return future
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700571
572 def connect(self, conn, address):
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300573 if conn.type == socket.SOCK_DGRAM:
574 # WSAConnect will complete immediately for UDP sockets so we don't
575 # need to register any IOCP operation
576 _overlapped.WSAConnect(conn.fileno(), address)
577 fut = self._loop.create_future()
578 fut.set_result(None)
579 return fut
580
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700581 self._register_with_iocp(conn)
582 # The socket needs to be locally bound before we call ConnectEx().
583 try:
584 _overlapped.BindLocal(conn.fileno(), conn.family)
585 except OSError as e:
586 if e.winerror != errno.WSAEINVAL:
587 raise
588 # Probably already locally bound; check using getsockname().
589 if conn.getsockname()[1] == 0:
590 raise
591 ov = _overlapped.Overlapped(NULL)
592 ov.ConnectEx(conn.fileno(), address)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700593
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700594 def finish_connect(trans, key, ov):
595 ov.getresult()
596 # Use SO_UPDATE_CONNECT_CONTEXT so getsockname() etc work.
597 conn.setsockopt(socket.SOL_SOCKET,
598 _overlapped.SO_UPDATE_CONNECT_CONTEXT, 0)
599 return conn
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700600
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700601 return self._register(ov, conn, finish_connect)
602
Andrew Svetlova19fb3c2018-02-25 19:32:14 +0300603 def sendfile(self, sock, file, offset, count):
604 self._register_with_iocp(sock)
605 ov = _overlapped.Overlapped(NULL)
606 offset_low = offset & 0xffff_ffff
607 offset_high = (offset >> 32) & 0xffff_ffff
608 ov.TransmitFile(sock.fileno(),
609 msvcrt.get_osfhandle(file.fileno()),
610 offset_low, offset_high,
611 count, 0, 0)
612
613 def finish_sendfile(trans, key, ov):
614 try:
615 return ov.getresult()
616 except OSError as exc:
617 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
618 _overlapped.ERROR_OPERATION_ABORTED):
619 raise ConnectionResetError(*exc.args)
620 else:
621 raise
622 return self._register(ov, sock, finish_sendfile)
623
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700624 def accept_pipe(self, pipe):
625 self._register_with_iocp(pipe)
626 ov = _overlapped.Overlapped(NULL)
Victor Stinner2b77c542015-01-22 23:50:03 +0100627 connected = ov.ConnectNamedPipe(pipe.fileno())
628
629 if connected:
630 # ConnectNamePipe() failed with ERROR_PIPE_CONNECTED which means
631 # that the pipe is connected. There is no need to wait for the
632 # completion of the connection.
Victor Stinner41063d22015-01-26 22:30:49 +0100633 return self._result(pipe)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700634
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100635 def finish_accept_pipe(trans, key, ov):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700636 ov.getresult()
637 return pipe
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700638
Victor Stinner2b77c542015-01-22 23:50:03 +0100639 return self._register(ov, pipe, finish_accept_pipe)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700640
Andrew Svetlov5f841b52017-12-09 00:23:48 +0200641 async def connect_pipe(self, address):
Victor Stinnere0fd1572015-01-26 15:04:03 +0100642 delay = CONNECT_PIPE_INIT_DELAY
643 while True:
Yury Selivanov6370f342017-12-10 18:36:12 -0500644 # Unfortunately there is no way to do an overlapped connect to
645 # a pipe. Call CreateFile() in a loop until it doesn't fail with
646 # ERROR_PIPE_BUSY.
Victor Stinnere0fd1572015-01-26 15:04:03 +0100647 try:
648 handle = _overlapped.ConnectPipe(address)
649 break
650 except OSError as exc:
651 if exc.winerror != _overlapped.ERROR_PIPE_BUSY:
652 raise
653
654 # ConnectPipe() failed with ERROR_PIPE_BUSY: retry later
655 delay = min(delay * 2, CONNECT_PIPE_MAX_DELAY)
Andrew Svetlov23b4b692019-05-27 22:56:22 +0300656 await tasks.sleep(delay)
Victor Stinnere0fd1572015-01-26 15:04:03 +0100657
658 return windows_utils.PipeHandle(handle)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700659
Guido van Rossum90fb9142013-10-30 14:44:05 -0700660 def wait_for_handle(self, handle, timeout=None):
Victor Stinner4d825b42014-12-19 17:10:44 +0100661 """Wait for a handle.
662
663 Return a Future object. The result of the future is True if the wait
664 completed, or False if the wait did not complete (on timeout).
665 """
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100666 return self._wait_for_handle(handle, timeout, False)
667
668 def _wait_cancel(self, event, done_callback):
669 fut = self._wait_for_handle(event, None, True)
670 # add_done_callback() cannot be used because the wait may only complete
671 # in IocpProactor.close(), while the event loop is not running.
672 fut._done_callback = done_callback
673 return fut
674
675 def _wait_for_handle(self, handle, timeout, _is_cancel):
Victor Stinner9b076812019-01-10 11:23:26 +0100676 self._check_closed()
677
Guido van Rossum90fb9142013-10-30 14:44:05 -0700678 if timeout is None:
679 ms = _winapi.INFINITE
680 else:
Victor Stinnerf2e17682014-01-31 16:25:24 +0100681 # RegisterWaitForSingleObject() has a resolution of 1 millisecond,
682 # round away from zero to wait *at least* timeout seconds.
683 ms = math.ceil(timeout * 1e3)
Guido van Rossum90fb9142013-10-30 14:44:05 -0700684
685 # We only create ov so we can use ov.address as a key for the cache.
686 ov = _overlapped.Overlapped(NULL)
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100687 wait_handle = _overlapped.RegisterWaitWithQueue(
Guido van Rossum90fb9142013-10-30 14:44:05 -0700688 handle, self._iocp, ov.address, ms)
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100689 if _is_cancel:
690 f = _WaitCancelFuture(ov, handle, wait_handle, loop=self._loop)
691 else:
692 f = _WaitHandleFuture(ov, handle, wait_handle, self,
693 loop=self._loop)
Victor Stinner313a9802014-07-29 12:58:23 +0200694 if f._source_traceback:
695 del f._source_traceback[-1]
Guido van Rossum90fb9142013-10-30 14:44:05 -0700696
Victor Stinnerc89c8a72014-02-26 17:35:30 +0100697 def finish_wait_for_handle(trans, key, ov):
Richard Oudkerk71196e72013-11-24 17:50:40 +0000698 # Note that this second wait means that we should only use
699 # this with handles types where a successful wait has no
700 # effect. So events or processes are all right, but locks
701 # or semaphores are not. Also note if the handle is
702 # signalled and then quickly reset, then we may return
703 # False even though we have not timed out.
Victor Stinner313a9802014-07-29 12:58:23 +0200704 return f._poll()
Guido van Rossum90fb9142013-10-30 14:44:05 -0700705
Victor Stinner313a9802014-07-29 12:58:23 +0200706 self._cache[ov.address] = (f, ov, 0, finish_wait_for_handle)
Guido van Rossum90fb9142013-10-30 14:44:05 -0700707 return f
708
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700709 def _register_with_iocp(self, obj):
710 # To get notifications of finished ops on this objects sent to the
711 # completion port, were must register the handle.
712 if obj not in self._registered:
713 self._registered.add(obj)
714 _overlapped.CreateIoCompletionPort(obj.fileno(), self._iocp, 0, 0)
715 # XXX We could also use SetFileCompletionNotificationModes()
716 # to avoid sending notifications to completion port of ops
717 # that succeed immediately.
718
Victor Stinner2b77c542015-01-22 23:50:03 +0100719 def _register(self, ov, obj, callback):
Victor Stinner9b076812019-01-10 11:23:26 +0100720 self._check_closed()
721
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700722 # Return a future which will be set with the result of the
723 # operation when it completes. The future's value is actually
724 # the value returned by callback().
725 f = _OverlappedFuture(ov, loop=self._loop)
Victor Stinner313a9802014-07-29 12:58:23 +0200726 if f._source_traceback:
727 del f._source_traceback[-1]
Victor Stinner2b77c542015-01-22 23:50:03 +0100728 if not ov.pending:
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700729 # The operation has completed, so no need to postpone the
730 # work. We cannot take this short cut if we need the
731 # NumberOfBytes, CompletionKey values returned by
732 # PostQueuedCompletionStatus().
733 try:
734 value = callback(None, None, ov)
735 except OSError as e:
736 f.set_exception(e)
737 else:
738 f.set_result(value)
Victor Stinner42d3bde2014-07-28 00:18:43 +0200739 # Even if GetOverlappedResult() was called, we have to wait for the
740 # notification of the completion in GetQueuedCompletionStatus().
741 # Register the overlapped operation to keep a reference to the
742 # OVERLAPPED object, otherwise the memory is freed and Windows may
743 # read uninitialized memory.
Victor Stinner2b77c542015-01-22 23:50:03 +0100744
745 # Register the overlapped operation for later. Note that
746 # we only store obj to prevent it from being garbage
747 # collected too early.
748 self._cache[ov.address] = (f, ov, obj, callback)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700749 return f
750
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100751 def _unregister(self, ov):
752 """Unregister an overlapped object.
753
754 Call this method when its future has been cancelled. The event can
755 already be signalled (pending in the proactor event queue). It is also
756 safe if the event is never signalled (because it was cancelled).
757 """
Victor Stinner9b076812019-01-10 11:23:26 +0100758 self._check_closed()
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100759 self._unregistered.append(ov)
760
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700761 def _get_accept_socket(self, family):
762 s = socket.socket(family)
763 s.settimeout(0)
764 return s
765
766 def _poll(self, timeout=None):
767 if timeout is None:
768 ms = INFINITE
769 elif timeout < 0:
770 raise ValueError("negative timeout")
771 else:
Victor Stinnerf2e17682014-01-31 16:25:24 +0100772 # GetQueuedCompletionStatus() has a resolution of 1 millisecond,
773 # round away from zero to wait *at least* timeout seconds.
774 ms = math.ceil(timeout * 1e3)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700775 if ms >= INFINITE:
776 raise ValueError("timeout too big")
Victor Stinner313a9802014-07-29 12:58:23 +0200777
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700778 while True:
779 status = _overlapped.GetQueuedCompletionStatus(self._iocp, ms)
780 if status is None:
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100781 break
Victor Stinner313a9802014-07-29 12:58:23 +0200782 ms = 0
783
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700784 err, transferred, key, address = status
785 try:
786 f, ov, obj, callback = self._cache.pop(address)
787 except KeyError:
Victor Stinner42d3bde2014-07-28 00:18:43 +0200788 if self._loop.get_debug():
789 self._loop.call_exception_handler({
790 'message': ('GetQueuedCompletionStatus() returned an '
791 'unexpected event'),
792 'status': ('err=%s transferred=%s key=%#x address=%#x'
793 % (err, transferred, key, address)),
794 })
795
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700796 # key is either zero, or it is used to return a pipe
797 # handle which should be closed to avoid a leak.
798 if key not in (0, _overlapped.INVALID_HANDLE_VALUE):
799 _winapi.CloseHandle(key)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700800 continue
Victor Stinner51e44ea2014-07-26 00:58:34 +0200801
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700802 if obj in self._stopped_serving:
803 f.cancel()
Victor Stinner42d3bde2014-07-28 00:18:43 +0200804 # Don't call the callback if _register() already read the result or
805 # if the overlapped has been cancelled
806 elif not f.done():
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700807 try:
808 value = callback(transferred, key, ov)
809 except OSError as e:
810 f.set_exception(e)
811 self._results.append(f)
812 else:
813 f.set_result(value)
814 self._results.append(f)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700815
Andrew Svetlov7a6706b2017-12-13 17:50:16 +0200816 # Remove unregistered futures
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100817 for ov in self._unregistered:
818 self._cache.pop(ov.address, None)
819 self._unregistered.clear()
820
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700821 def _stop_serving(self, obj):
822 # obj is a socket or pipe handle. It will be closed in
823 # BaseProactorEventLoop._stop_serving() which will make any
824 # pending operations fail quickly.
825 self._stopped_serving.add(obj)
826
827 def close(self):
Victor Stinner9b076812019-01-10 11:23:26 +0100828 if self._iocp is None:
829 # already closed
830 return
831
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700832 # Cancel remaining registered operations.
Victor Stinnerfea6a102014-07-25 00:54:53 +0200833 for address, (fut, ov, obj, callback) in list(self._cache.items()):
Victor Stinner3d2256f2015-01-26 11:02:59 +0100834 if fut.cancelled():
Victor Stinner752aba72015-01-22 22:47:13 +0100835 # Nothing to do with cancelled futures
836 pass
Victor Stinner1ca93922015-01-22 00:17:54 +0100837 elif isinstance(fut, _WaitCancelFuture):
838 # _WaitCancelFuture must not be cancelled
839 pass
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700840 else:
841 try:
Victor Stinnerfea6a102014-07-25 00:54:53 +0200842 fut.cancel()
843 except OSError as exc:
844 if self._loop is not None:
845 context = {
846 'message': 'Cancelling a future failed',
847 'exception': exc,
848 'future': fut,
849 }
850 if fut._source_traceback:
851 context['source_traceback'] = fut._source_traceback
852 self._loop.call_exception_handler(context)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700853
Victor Stinnerb1e45732019-01-15 11:48:00 +0100854 # Wait until all cancelled overlapped complete: don't exit with running
855 # overlapped to prevent a crash. Display progress every second if the
856 # loop is still running.
857 msg_update = 1.0
858 start_time = time.monotonic()
859 next_msg = start_time + msg_update
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700860 while self._cache:
Victor Stinnerb1e45732019-01-15 11:48:00 +0100861 if next_msg <= time.monotonic():
Victor Stinnerb91140f2019-01-15 12:13:48 +0100862 logger.debug('%r is running after closing for %.1f seconds',
863 self, time.monotonic() - start_time)
Victor Stinnerb1e45732019-01-15 11:48:00 +0100864 next_msg = time.monotonic() + msg_update
865
866 # handle a few events, or timeout
867 self._poll(msg_update)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700868
869 self._results = []
Victor Stinner9b076812019-01-10 11:23:26 +0100870
871 _winapi.CloseHandle(self._iocp)
872 self._iocp = None
Guido van Rossum59691282013-10-30 14:52:03 -0700873
Victor Stinnerfea6a102014-07-25 00:54:53 +0200874 def __del__(self):
875 self.close()
876
Guido van Rossum59691282013-10-30 14:52:03 -0700877
878class _WindowsSubprocessTransport(base_subprocess.BaseSubprocessTransport):
879
880 def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
881 self._proc = windows_utils.Popen(
882 args, shell=shell, stdin=stdin, stdout=stdout, stderr=stderr,
883 bufsize=bufsize, **kwargs)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700884
Guido van Rossum59691282013-10-30 14:52:03 -0700885 def callback(f):
886 returncode = self._proc.poll()
887 self._process_exited(returncode)
Guido van Rossuma8d630a2013-11-01 14:20:55 -0700888
Guido van Rossum59691282013-10-30 14:52:03 -0700889 f = self._loop._proactor.wait_for_handle(int(self._proc._handle))
890 f.add_done_callback(callback)
Guido van Rossum0eaa5ac2013-11-04 15:50:46 -0800891
892
893SelectorEventLoop = _WindowsSelectorEventLoop
894
895
Yury Selivanov8f404292018-06-07 20:44:57 -0400896class WindowsSelectorEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
Guido van Rossum0eaa5ac2013-11-04 15:50:46 -0800897 _loop_factory = SelectorEventLoop
898
899
Yury Selivanov8f404292018-06-07 20:44:57 -0400900class WindowsProactorEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
901 _loop_factory = ProactorEventLoop
902
903
Victor Stinner6ea29c52018-09-25 08:27:08 -0700904DefaultEventLoopPolicy = WindowsProactorEventLoopPolicy