diff options
author | Zac Medico <zmedico@gentoo.org> | 2009-06-22 16:43:52 +0000 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2009-06-22 16:43:52 +0000 |
commit | d057d91f391981fb0564873c471d550f2f62edf5 (patch) | |
tree | d6cd416fc5e9389806ec98a02ae236c99e876e4b /pym/_emerge/SubProcess.py | |
parent | 28184c982a0688ed9bc4d82df407d4e400f6318c (diff) | |
download | portage-d057d91f391981fb0564873c471d550f2f62edf5.tar.gz portage-d057d91f391981fb0564873c471d550f2f62edf5.tar.bz2 portage-d057d91f391981fb0564873c471d550f2f62edf5.zip |
Bug #275047 - Split _emerge/__init__.py into smaller pieces. Thanks to
Sebastian Mingramm (few) <s.mingramm@gmx.de> for this patch.
svn path=/main/trunk/; revision=13663
Diffstat (limited to 'pym/_emerge/SubProcess.py')
-rw-r--r-- | pym/_emerge/SubProcess.py | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/pym/_emerge/SubProcess.py b/pym/_emerge/SubProcess.py new file mode 100644 index 000000000..67d682bc5 --- /dev/null +++ b/pym/_emerge/SubProcess.py @@ -0,0 +1,104 @@ +from _emerge.AbstractPollTask import AbstractPollTask +import signal +import os +import errno +class SubProcess(AbstractPollTask): + + __slots__ = ("pid",) + \ + ("_files", "_reg_id") + + # A file descriptor is required for the scheduler to monitor changes from + # inside a poll() loop. When logging is not enabled, create a pipe just to + # serve this purpose alone. + _dummy_pipe_fd = 9 + + 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: + 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) + return self.returncode + + def cancel(self): + if self.isAlive(): + 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() + return self.returncode + + def isAlive(self): + return self.pid is not None and \ + self.returncode is None + + def _wait(self): + + if self.returncode is not None: + return self.returncode + + if self._registered: + self.scheduler.schedule(self._reg_id) + self._unregister() + if self.returncode is not None: + return self.returncode + + 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 _unregister(self): + """ + Unregister from the scheduler and close open files. + """ + + self._registered = False + + if self._reg_id is not None: + self.scheduler.unregister(self._reg_id) + self._reg_id = None + + if self._files is not None: + for f in self._files.itervalues(): + f.close() + self._files = None + + def _set_returncode(self, wait_retval): + + retval = wait_retval[1] + + if retval != os.EX_OK: + if retval & 0xff: + retval = (retval & 0xff) << 8 + else: + retval = retval >> 8 + + self.returncode = retval + |