public inbox for gentoo-portage-dev@lists.gentoo.org
 help / color / mirror / Atom feed
From: Zac Medico <zmedico@gentoo.org>
To: gentoo-portage-dev@lists.gentoo.org
Cc: Zac Medico <zmedico@gentoo.org>
Subject: [gentoo-portage-dev] [PATCH] AsyncioEventLoop: wrap child watcher for thread safety (bug 764905)
Date: Sun, 10 Jan 2021 23:19:33 -0800	[thread overview]
Message-ID: <20210111071933.231869-1-zmedico@gentoo.org> (raw)

Use a child watcher wrapper to deliver the callbacks via the
call_soon_threadsafe method, since documentation for the asycio
AbstractChildWatcher class says that callbacks must be thread
safe.

Bug: https://bugs.gentoo.org/764905
Signed-off-by: Zac Medico <zmedico@gentoo.org>
---
 .../util/_eventloop/asyncio_event_loop.py     | 30 ++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/lib/portage/util/_eventloop/asyncio_event_loop.py b/lib/portage/util/_eventloop/asyncio_event_loop.py
index 4d7047ae8..b77728088 100644
--- a/lib/portage/util/_eventloop/asyncio_event_loop.py
+++ b/lib/portage/util/_eventloop/asyncio_event_loop.py
@@ -6,6 +6,7 @@ import signal
 
 import asyncio as _real_asyncio
 from asyncio.events import AbstractEventLoop as _AbstractEventLoop
+from asyncio.unix_events import AbstractChildWatcher as _AbstractChildWatcher
 
 import portage
 
@@ -47,6 +48,7 @@ class AsyncioEventLoop(_AbstractEventLoop):
 		self.set_debug = loop.set_debug
 		self.get_debug = loop.get_debug
 		self._wakeup_fd = -1
+		self._child_watcher = None
 
 		if portage._internal_caller:
 			loop.set_exception_handler(self._internal_caller_exception_handler)
@@ -87,7 +89,9 @@ class AsyncioEventLoop(_AbstractEventLoop):
 		@rtype: asyncio.AbstractChildWatcher
 		@return: the internal event loop's AbstractChildWatcher interface
 		"""
-		return _real_asyncio.get_child_watcher()
+		if self._child_watcher is None:
+			self._child_watcher = _ChildWatcherThreadSafetyWrapper(self, _real_asyncio.get_child_watcher())
+		return self._child_watcher
 
 	@property
 	def _asyncio_wrapper(self):
@@ -126,3 +130,27 @@ class AsyncioEventLoop(_AbstractEventLoop):
 			except ValueError:
 				# This is intended to fail when not called in the main thread.
 				pass
+
+
+class _ChildWatcherThreadSafetyWrapper(_AbstractChildWatcher):
+	def __init__(self, loop, real_watcher):
+		self._loop = loop
+		self._real_watcher = real_watcher
+
+	def close(self):
+		pass
+
+	def __enter__(self):
+		return self
+
+	def __exit__(self, a, b, c):
+		pass
+
+	def _child_exit(self, pid, status, callback, *args):
+		self._loop.call_soon_threadsafe(callback, pid, status, *args)
+
+	def add_child_handler(self, pid, callback, *args):
+		self._real_watcher.add_child_handler(pid, self._child_exit, callback, *args)
+
+	def remove_child_handler(self, pid):
+		return self._real_watcher.remove_child_handler(pid)
-- 
2.26.2



                 reply	other threads:[~2021-01-11  7:19 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20210111071933.231869-1-zmedico@gentoo.org \
    --to=zmedico@gentoo.org \
    --cc=gentoo-portage-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