From ed2e6097e86b078fd76a98ba9d261dfb3c1f9f39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= <sybren@stuvel.eu>
Date: Wed, 4 Jan 2017 10:35:35 +0100
Subject: [PATCH] Worker: construct ProactorEventLoop on Windows

On Windows, the default event loop is SelectorEventLoop which does
not support subprocesses. ProactorEventLoop should be used instead.

Source: https://docs.python.org/3.5/library/asyncio-subprocess.html
---
 .../flamenco_worker/cli.py                      | 17 ++++++++++++++++-
 .../tests/test_upstream_update_queue.py         |  3 ++-
 .../flamenco-worker-python/tests/test_worker.py |  7 +++++--
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/packages/flamenco-worker-python/flamenco_worker/cli.py b/packages/flamenco-worker-python/flamenco_worker/cli.py
index 90e499c7..9c2177a9 100644
--- a/packages/flamenco-worker-python/flamenco_worker/cli.py
+++ b/packages/flamenco-worker-python/flamenco_worker/cli.py
@@ -54,7 +54,7 @@ def main():
     confparser = config.load_config(args.config, args.verbose)
 
     # Construct the AsyncIO loop
-    loop = asyncio.get_event_loop()
+    loop = construct_asyncio_loop()
     if args.verbose:
         log.debug('Enabling AsyncIO debugging')
         loop.set_debug(True)
@@ -111,5 +111,20 @@ def main():
     log.warning('Shutting down')
 
 
+def construct_asyncio_loop() -> asyncio.AbstractEventLoop:
+    # On Windows, the default event loop is SelectorEventLoop which does
+    # not support subprocesses. ProactorEventLoop should be used instead.
+    # Source: https://docs.python.org/3.5/library/asyncio-subprocess.html
+    import sys
+
+    if sys.platform == 'win32':
+        loop = asyncio.ProactorEventLoop()
+        asyncio.set_event_loop(loop)
+    else:
+        loop = asyncio.get_event_loop()
+
+    return loop
+
+
 if __name__ == '__main__':
     main()
diff --git a/packages/flamenco-worker-python/tests/test_upstream_update_queue.py b/packages/flamenco-worker-python/tests/test_upstream_update_queue.py
index 6f7536c2..9d5527f6 100644
--- a/packages/flamenco-worker-python/tests/test_upstream_update_queue.py
+++ b/packages/flamenco-worker-python/tests/test_upstream_update_queue.py
@@ -13,9 +13,10 @@ class TaskUpdateQueueTest(AbstractWorkerTest):
     def setUp(self):
         from flamenco_worker.upstream import FlamencoManager
         from flamenco_worker.upstream_update_queue import TaskUpdateQueue
+        from flamenco_worker.cli import construct_asyncio_loop
         from mock_responses import CoroMock
 
-        self.asyncio_loop = asyncio.get_event_loop()
+        self.asyncio_loop = construct_asyncio_loop()
         self.shutdown_future = self.asyncio_loop.create_future()
 
         self.manager = Mock(spec=FlamencoManager)
diff --git a/packages/flamenco-worker-python/tests/test_worker.py b/packages/flamenco-worker-python/tests/test_worker.py
index 228bef28..89ef0209 100644
--- a/packages/flamenco-worker-python/tests/test_worker.py
+++ b/packages/flamenco-worker-python/tests/test_worker.py
@@ -8,12 +8,13 @@ import requests
 
 class AbstractWorkerTest(unittest.TestCase):
     def setUp(self):
+        from flamenco_worker.cli import construct_asyncio_loop
         from flamenco_worker.upstream import FlamencoManager
         from flamenco_worker.worker import FlamencoWorker
         from flamenco_worker.runner import TaskRunner
         from flamenco_worker.upstream_update_queue import TaskUpdateQueue
 
-        self.asyncio_loop = asyncio.get_event_loop()
+        self.asyncio_loop = construct_asyncio_loop()
         self.shutdown_future = self.asyncio_loop.create_future()
 
         self.manager = Mock(spec=FlamencoManager)
@@ -116,7 +117,9 @@ class WorkerStartupTest(AbstractWorkerTest):
 class TestWorkerTaskFetch(AbstractWorkerTest):
     def setUp(self):
         super().setUp()
-        self.loop = asyncio.get_event_loop()
+        from flamenco_worker.cli import construct_asyncio_loop
+
+        self.loop = construct_asyncio_loop()
         self.worker.loop = self.loop
 
     def run_loop_for(self, seconds: float):
-- 
GitLab