--- a/bin/emerge +++ a/bin/emerge @@ -2890,7 +2890,25 @@ class MergeTask(object): self.pkgsettings["/"] = \ portage.config(clone=trees["/"]["vartree"].settings) + def _signal_handler(self, signum, frame): + self._interrupt_count += 1 + if self._interrupt_count > 1: + signal.signal(signal.SIGINT, signal.SIG_IGN) + signal.signal(signal.SIGTERM, signal.SIG_IGN) + portage.writemsg( + "\n\nExiting on signal %(signal)s\n" % {"signal":signum}) + sys.exit(100+signum) + else: + portage.writemsg( + "\n\nCaught signal: waiting until this ebuild finishes..." + \ + " Try again to force stop now\n", noiselevel=-1) + def merge(self, mylist, favorites, mtimedb): + + self._interrupt_count = 0 + signal.signal(signal.SIGINT, self._signal_handler) + signal.signal(signal.SIGTERM, self._signal_handler) + failed_fetches = [] mymergelist=[] ldpath_mtimes = mtimedb["ldpath"] @@ -3302,6 +3320,8 @@ class MergeTask(object): # in the event that portage is not allowed to exit normally # due to power failure, SIGKILL, etc... mtimedb.commit() + if self._interrupt_count: + break if "--pretend" not in self.myopts: emergelog(xterm_titles, " *** Finished. Cleaning up...") --- a/pym/portage.py +++ a/pym/portage.py @@ -2246,13 +2246,28 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keyw while mypids: pid = mypids.pop(0) - retval = os.waitpid(pid, 0)[1] + while True: + try: + retval = os.waitpid(pid, 0)[1] + break + except OSError, e: + if e.errno != errno.EINTR: + raise + del e portage_exec.spawned_pids.remove(pid) if retval != os.EX_OK: for pid in mypids: if os.waitpid(pid, os.WNOHANG) == (0,0): + import signal os.kill(pid, signal.SIGTERM) - os.waitpid(pid, 0) + while True: + try: + os.waitpid(pid, 0) + break + except OSError, e: + if e.errno != errno.EINTR: + raise + del e portage_exec.spawned_pids.remove(pid) if retval & 0xff: return (retval & 0xff) << 8