From dcf36ddfe69c9a2dd65fc80731623d719fe49954 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Thu, 10 Jul 2008 01:24:43 +0000 Subject: * Handle errno.ECHILD and errno.ESRCH from waitpid() and kill() calls. These errors commonly occur when ^C is used to kill emerge. * Remove spawned pids from portage.process.spawned_pids immediately in order to avoid a race condition for removing it. svn path=/main/trunk/; revision=11007 --- pym/_emerge/__init__.py | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 73ce61c61..a1a3d6fe7 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -1712,7 +1712,15 @@ class SubProcess(AsynchronousTask): return self.returncode if self.pid is None: return self.returncode - retval = os.waitpid(self.pid, os.WNOHANG) + + try: + retval = os.waitpid(self.pid, os.WNOHANG) + except OSError, e: + if e.errno != errno.ECHILD: + raise + del e + retval = (self.pid, 1) + if retval == (0, 0): return None self._set_returncode(retval) @@ -1720,7 +1728,13 @@ class SubProcess(AsynchronousTask): def cancel(self): if self.isAlive(): - os.kill(self.pid, signal.SIGTERM) + try: + os.kill(self.pid, signal.SIGTERM) + except OSError, e: + if e.errno != errno.ESRCH: + raise + del e + self.cancelled = True if self.pid is not None: self.wait() @@ -1735,13 +1749,21 @@ class SubProcess(AsynchronousTask): return self.returncode if self.registered: self.scheduler.schedule(self._reg_id) - self._set_returncode(os.waitpid(self.pid, 0)) + try: + wait_retval = os.waitpid(self.pid, 0) + except OSError, e: + if e.errno != errno.ECHILD: + raise + del e + self._set_returncode((self.pid, 1)) + else: + self._set_returncode(wait_retval) return self.returncode def _set_returncode(self, wait_retval): retval = wait_retval[1] - portage.process.spawned_pids.remove(self.pid) + if retval != os.EX_OK: if retval & 0xff: retval = (retval & 0xff) << 8 @@ -1833,6 +1855,7 @@ class SpawnProcess(SubProcess): retval = portage.process.spawn(self.args, **kwargs) self.pid = retval[0] + portage.process.spawned_pids.remove(self.pid) os.close(slave_fd) files.process = os.fdopen(master_fd, 'r') @@ -2358,6 +2381,7 @@ class EbuildPhase(SubProcess): fd_pipes=fd_pipes, returnpid=True) self.pid = retval[0] + portage.process.spawned_pids.remove(self.pid) if logfile: files.log = open(logfile, 'a') -- cgit v1.2.3-1-g7c22