commit:     b530e4e67b843837093e545cf81fd4ab8336d2c2
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Sun Apr 29 21:09:59 2018 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Sun Apr 29 21:26:37 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=b530e4e6

SubProcess: add_child_handler asyncio compat (bug 654276)

Migrate to asyncio's AbstractChildWatcher.add_child_handler
interface. Re-use PopenProcess code introduced in commit
be800bf0153a28ce034277d103a2021f93ac8b2e. Also remove the
child_watch_add method from SchedulerInterface, since there
are no more consumers.

Bug: https://bugs.gentoo.org/654276

 pym/_emerge/SubProcess.py                     | 58 ++++-----------------------
 pym/portage/util/_async/PopenProcess.py       | 20 ++-------
 pym/portage/util/_async/SchedulerInterface.py |  1 -
 3 files changed, 11 insertions(+), 68 deletions(-)

diff --git a/pym/_emerge/SubProcess.py b/pym/_emerge/SubProcess.py
index 3939de3ed..aa4778737 100644
--- a/pym/_emerge/SubProcess.py
+++ b/pym/_emerge/SubProcess.py
@@ -19,28 +19,7 @@ class SubProcess(AbstractPollTask):
        _cancel_timeout = 1000 # 1 second
 
        def _poll(self):
-               if self.returncode is not None:
-                       return self.returncode
-               if self.pid is None:
-                       return self.returncode
-               if self._registered:
-                       return self.returncode
-
-               try:
-                       # With waitpid and WNOHANG, only check the
-                       # first element of the tuple since the second
-                       # element may vary (bug #337465).
-                       retval = os.waitpid(self.pid, os.WNOHANG)
-               except OSError as e:
-                       if e.errno != errno.ECHILD:
-                               raise
-                       del e
-                       retval = (self.pid, 1)
-
-               if retval[0] == 0:
-                       return None
-               self._set_returncode(retval)
-               self._async_wait()
+               # Simply rely on _async_waitpid_cb to set the returncode.
                return self.returncode
 
        def _cancel(self):
@@ -71,20 +50,16 @@ class SubProcess(AbstractPollTask):
                if self.returncode is not None:
                        self._async_wait()
                elif self._waitpid_id is None:
-                       self._waitpid_id = self.scheduler.child_watch_add(
-                               self.pid, self._async_waitpid_cb)
+                       self._waitpid_id = self.pid
+                       self.scheduler._asyncio_child_watcher.\
+                               add_child_handler(self.pid, 
self._async_waitpid_cb)
 
-       def _async_waitpid_cb(self, pid, condition, user_data=None):
+       def _async_waitpid_cb(self, pid, returncode):
                if pid != self.pid:
                        raise AssertionError("expected pid %s, got %s" % 
(self.pid, pid))
-               self._set_returncode((pid, condition))
+               self.returncode = returncode
                self._async_wait()
 
-       def _waitpid_cb(self, pid, condition, user_data=None):
-               if pid != self.pid:
-                       raise AssertionError("expected pid %s, got %s" % 
(self.pid, pid))
-               self._set_returncode((pid, condition))
-
        def _orphan_process_warn(self):
                pass
 
@@ -100,7 +75,8 @@ class SubProcess(AbstractPollTask):
                        self._reg_id = None
 
                if self._waitpid_id is not None:
-                       self.scheduler.source_remove(self._waitpid_id)
+                       self.scheduler._asyncio_child_watcher.\
+                               remove_child_handler(self._waitpid_id)
                        self._waitpid_id = None
 
                if self._files is not None:
@@ -126,21 +102,3 @@ class SubProcess(AbstractPollTask):
                        elif event & self.scheduler.IO_HUP:
                                self._unregister()
                                self._async_waitpid()
-
-       def _set_returncode(self, wait_retval):
-               """
-               Set the returncode in a manner compatible with
-               subprocess.Popen.returncode: A negative value -N indicates
-               that the child was terminated by signal N (Unix only).
-               """
-               self._unregister()
-
-               pid, status = wait_retval
-
-               if os.WIFSIGNALED(status):
-                       retval = - os.WTERMSIG(status)
-               else:
-                       retval = os.WEXITSTATUS(status)
-
-               self.returncode = retval
-

diff --git a/pym/portage/util/_async/PopenProcess.py 
b/pym/portage/util/_async/PopenProcess.py
index 3fb60d527..c1931327a 100644
--- a/pym/portage/util/_async/PopenProcess.py
+++ b/pym/portage/util/_async/PopenProcess.py
@@ -25,23 +25,9 @@ class PopenProcess(SubProcess):
        def _pipe_reader_exit(self, pipe_reader):
                self._async_waitpid()
 
-       def _async_waitpid(self):
-               if self.returncode is None:
-                       self.scheduler._asyncio_child_watcher.\
-                               add_child_handler(self.pid, 
self._async_waitpid_cb)
-               else:
-                       self._unregister()
-                       self._async_wait()
-
-       def _async_waitpid_cb(self, pid, returncode):
+       def _async_waitpid_cb(self, *args, **kwargs):
+               SubProcess._async_waitpid_cb(self, *args, **kwargs)
                if self.proc.returncode is None:
                        # Suppress warning messages like this:
                        # ResourceWarning: subprocess 1234 is still running
-                       self.proc.returncode = returncode
-               self._unregister()
-               self.returncode = returncode
-               self._async_wait()
-
-       def _poll(self):
-               # Simply rely on _async_waitpid_cb to set the returncode.
-               return self.returncode
+                       self.proc.returncode = self.returncode

diff --git a/pym/portage/util/_async/SchedulerInterface.py 
b/pym/portage/util/_async/SchedulerInterface.py
index be118ae0e..ff39bc587 100644
--- a/pym/portage/util/_async/SchedulerInterface.py
+++ b/pym/portage/util/_async/SchedulerInterface.py
@@ -13,7 +13,6 @@ class SchedulerInterface(SlotObject):
 
        _event_loop_attrs = ("IO_ERR", "IO_HUP", "IO_IN",
                "IO_NVAL", "IO_OUT", "IO_PRI",
-               "child_watch_add",
                "io_add_watch",
                "source_remove",
                "timeout_add",

Reply via email to