public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Zac Medico" <zmedico@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/tests/util/
Date: Thu, 22 Feb 2024 15:36:40 +0000 (UTC)	[thread overview]
Message-ID: <1708586918.fbaaa4a733aaadc2744b656527756ac4e2b7ab58.zmedico@gentoo> (raw)

commit:     fbaaa4a733aaadc2744b656527756ac4e2b7ab58
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Thu Feb 22 06:47:33 2024 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Thu Feb 22 07:28:38 2024 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=fbaaa4a7

socks5: Use real asyncio.run

Use real asyncio.run to demonstrate that it is compatible with
portage internals. Since the socks5 ProxyManager uses the
process.spawn function, the internal _running_loop function
needs to return the correct loop for use in the wait method of
MultiprocessingProcess, or else it will lead to Future
"attached to a different loop" errors.

Bug: https://bugs.gentoo.org/761538
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 lib/portage/tests/util/test_socks5.py | 45 +++++++++++++++++++----------------
 lib/portage/util/socks5.py            | 30 ++++++++++++++++-------
 2 files changed, 46 insertions(+), 29 deletions(-)

diff --git a/lib/portage/tests/util/test_socks5.py b/lib/portage/tests/util/test_socks5.py
index 987b41af29..7b33cb3f6b 100644
--- a/lib/portage/tests/util/test_socks5.py
+++ b/lib/portage/tests/util/test_socks5.py
@@ -1,6 +1,7 @@
-# Copyright 2019-2021 Gentoo Authors
+# Copyright 2019-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
+import asyncio
 import functools
 import shutil
 import socket
@@ -10,7 +11,6 @@ import time
 
 import portage
 from portage.tests import TestCase
-from portage.util._eventloop.global_event_loop import global_event_loop
 from portage.util import socks5
 from portage.const import PORTAGE_BIN_PATH
 
@@ -88,18 +88,20 @@ class AsyncHTTPServerTestCase(TestCase):
             if f is not None:
                 f.close()
 
-    def test_http_server(self):
+    async def _test_http_server(self):
+        asyncio.run(self._test_http_server())
+
+    async def _test_http_server(self):
         host = "127.0.0.1"
         content = b"Hello World!\n"
         path = "/index.html"
-        loop = global_event_loop()
+
+        loop = asyncio.get_running_loop()
         for i in range(2):
             with AsyncHTTPServer(host, {path: content}, loop) as server:
                 for j in range(2):
-                    result = loop.run_until_complete(
-                        loop.run_in_executor(
-                            None, self._fetch_directly, host, server.server_port, path
-                        )
+                    result = await loop.run_in_executor(
+                        None, self._fetch_directly, host, server.server_port, path
                     )
                     self.assertEqual(result, content)
 
@@ -177,7 +179,10 @@ class Socks5ServerTestCase(TestCase):
             return f.read()
 
     def test_socks5_proxy(self):
-        loop = global_event_loop()
+        asyncio.run(self._test_socks5_proxy())
+
+    async def _test_socks5_proxy(self):
+        loop = asyncio.get_running_loop()
 
         host = "127.0.0.1"
         content = b"Hello World!"
@@ -193,20 +198,18 @@ class Socks5ServerTestCase(TestCase):
                 }
 
                 proxy = socks5.get_socks5_proxy(settings)
-                loop.run_until_complete(socks5.proxy.ready())
-
-                result = loop.run_until_complete(
-                    loop.run_in_executor(
-                        None,
-                        self._fetch_via_proxy,
-                        proxy,
-                        host,
-                        server.server_port,
-                        path,
-                    )
+                await socks5.proxy.ready()
+
+                result = await loop.run_in_executor(
+                    None,
+                    self._fetch_via_proxy,
+                    proxy,
+                    host,
+                    server.server_port,
+                    path,
                 )
 
                 self.assertEqual(result, content)
         finally:
-            socks5.proxy.stop()
+            await socks5.proxy.stop()
             shutil.rmtree(tempdir)

diff --git a/lib/portage/util/socks5.py b/lib/portage/util/socks5.py
index 6c68ff4106..74592aeefe 100644
--- a/lib/portage/util/socks5.py
+++ b/lib/portage/util/socks5.py
@@ -2,15 +2,16 @@
 # Copyright 2015-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
+import asyncio
 import errno
 import os
 import socket
+from typing import Union
 
 import portage.data
 from portage import _python_interpreter
 from portage.data import portage_gid, portage_uid, userpriv_groups
 from portage.process import atexit_register, spawn
-from portage.util.futures import asyncio
 
 
 class ProxyManager:
@@ -57,23 +58,36 @@ class ProxyManager:
             **spawn_kwargs,
         )
 
-    def stop(self):
+    def stop(self) -> Union[None, asyncio.Future]:
         """
         Stop the SOCKSv5 server.
+
+        If there is a running asyncio event loop then asyncio.Future is
+        returned which should be used to wait for the server process
+        to exit.
         """
+        future = None
+        try:
+            loop = asyncio.get_running_loop()
+        except RuntimeError:
+            loop = None
         if self._proc is not None:
             self._proc.terminate()
-            loop = asyncio.get_event_loop()
-            if self._proc_waiter is None:
-                self._proc_waiter = asyncio.ensure_future(self._proc.wait(), loop)
-            if loop.is_running():
-                self._proc_waiter.add_done_callback(lambda future: future.result())
+            if loop is None:
+                asyncio.run(self._proc.wait())
             else:
-                loop.run_until_complete(self._proc_waiter)
+                if self._proc_waiter is None:
+                    self._proc_waiter = asyncio.ensure_future(self._proc.wait(), loop)
+                future = asyncio.shield(self._proc_waiter)
+
+        if loop is not None and future is None:
+            future = loop.create_future()
+            future.set_result(None)
 
         self.socket_path = None
         self._proc = None
         self._proc_waiter = None
+        return future
 
     def is_running(self):
         """


             reply	other threads:[~2024-02-22 15:36 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-22 15:36 Zac Medico [this message]
  -- strict thread matches above, loose matches on Subject: below --
2022-12-31 13:33 [gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/tests/util/ Sam James
2022-06-07 23:48 Mike Gilbert
2022-06-07 23:48 Mike Gilbert
2022-06-07 23:48 Mike Gilbert
2022-06-07 23:48 Mike Gilbert
2019-01-16  8:33 Zac Medico

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1708586918.fbaaa4a733aaadc2744b656527756ac4e2b7ab58.zmedico@gentoo \
    --to=zmedico@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox