From 6557c596b6e3dd749c5bad942d10621e908b1f0d Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 6 Feb 2006 19:25:08 +0000 Subject: [PATCH] wrap all relevant atexit usage due to incompatibility with os.execv (needed for emerge to restart itself) svn path=/main/trunk/; revision=2674 --- bin/emerge | 6 +++--- pym/portage.py | 5 +++-- pym/portage_exec.py | 36 +++++++++++++++++++++++++++++++++++- pym/portage_locks.py | 4 ++-- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/bin/emerge b/bin/emerge index e9aa65dd5..f9cd87081 100755 --- a/bin/emerge +++ b/bin/emerge @@ -9,7 +9,7 @@ sys.path = ["/usr/lib/portage/pym"]+sys.path import portage -import emergehelp,xpak,string,re,commands,time,shutil,traceback,atexit,signal,socket,types +import emergehelp,xpak,string,re,commands,time,shutil,traceback,signal,socket,types from stat import * from output import * @@ -492,7 +492,7 @@ def emergeexit(): emergelog(" *** terminating.") if "notitles" not in portage.features: xtermTitleReset() -atexit.register(emergeexit) +portage.atexit_register(emergeexit) def emergeexitsig(signum, frame): signal.signal(signal.SIGINT, signal.SIG_IGN) @@ -2119,7 +2119,7 @@ class depgraph: if len(mymergelist) > mergecount: emergelog(" *** RESTARTING emerge via exec() after change of portage version.") del portage.mtimedb["resume"]["mergelist"][0] - portage.portageexit() + portage.run_exitfuncs() mynewargv=[sys.argv[0],"--resume"] badlongopts = ("--ask","--tree","--changelog","--skipfirst","--resume") for arg in myopts: diff --git a/pym/portage.py b/pym/portage.py index f5949bd5e..abc48ddf2 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -19,7 +19,7 @@ except: raise SystemExit, 127 try: - import os,string,types,atexit,signal,fcntl + import os,string,types,signal,fcntl import time,cPickle,traceback,copy import re,pwd,grp,commands import shlex,shutil @@ -95,6 +95,7 @@ try: import portage_gpg import portage_locks import portage_exec + from portage_exec import atexit_register, run_exitfuncs from portage_locks import unlockfile,unlockdir,lockfile,lockdir import portage_checksum from portage_checksum import perform_md5,perform_checksum,prelink_capable @@ -6901,7 +6902,7 @@ def portageexit(): close_portdbapi_caches() commit_mtimedb() -atexit.register(portageexit) +atexit_register(portageexit) if (secpass==2) and (not os.environ.has_key("SANDBOX_ACTIVE")): if settings["PORTAGE_CALLER"] in ["emerge","fixpackages"]: diff --git a/pym/portage_exec.py b/pym/portage_exec.py index db3c8be36..31b379396 100644 --- a/pym/portage_exec.py +++ b/pym/portage_exec.py @@ -7,6 +7,7 @@ import os, atexit, signal, sys import portage_data +from portage_util import dump_traceback from portage_const import BASH_BINARY, SANDBOX_BINARY @@ -39,6 +40,39 @@ def spawn_sandbox(mycommand, opt_name=None, **keywords): args.append(mycommand) return spawn(args, opt_name=opt_name, **keywords) +_exithandlers = [] +def atexit_register(func, *args, **kargs): + """Wrapper around atexit.register that is needed in order to track + what is registered. For example, when portage restarts itself via + os.execv, the atexit module does not work so we have to do it + manually by calling the run_exitfuncs() function in this module.""" + _exithandlers.append((func, args, kargs)) + +def run_exitfuncs(): + """This should behave identically to the routine performed by + the atexit module at exit time. It's only necessary to call this + function when atexit will not work (because of os.execv, for + example).""" + + # This function is a copy of the private atexit._run_exitfuncs() + # from the python 2.4.2 sources. The only difference from the + # original function is in the output to stderr. + exc_info = None + while _exithandlers: + func, targs, kargs = _exithandlers.pop() + try: + func(*targs, **kargs) + except SystemExit: + exc_info = sys.exc_info() + except: + dump_traceback("Error in portage_exec.run_exitfuncs", noiselevel=0) + exc_info = sys.exc_info() + + if exc_info is not None: + raise exc_info[0], exc_info[1], exc_info[2] + +atexit.register(run_exitfuncs) + # We need to make sure that any processes spawned are killed off when # we exit. spawn() takes care of adding and removing pids to this list # as it creates and cleans up processes. @@ -55,7 +89,7 @@ def cleanup(): # of spawn(). pass -atexit.register(cleanup) +atexit_register(cleanup) def spawn(mycommand, env={}, opt_name=None, fd_pipes=None, returnpid=False, uid=None, gid=None, groups=None, umask=None, logfile=None, diff --git a/pym/portage_locks.py b/pym/portage_locks.py index 241ff9df9..09daa2e4d 100644 --- a/pym/portage_locks.py +++ b/pym/portage_locks.py @@ -4,7 +4,6 @@ # $Id: /var/cvsroot/gentoo-src/portage/pym/portage_locks.py,v 1.18.2.2 2005/01/16 02:35:33 carpaski Exp $ -import atexit import errno import os import stat @@ -15,6 +14,7 @@ import portage_exception import portage_file import portage_util import portage_data +from portage_exec import atexit_register from portage_localization import _ HARDLINK_FD = -2 @@ -30,7 +30,7 @@ def add_hardlock_file_to_cleanup(path): if os.path.isdir(mypath): hardlock_path_list = mypath[:] -atexit.register(clean_my_hardlocks) +atexit_register(clean_my_hardlocks) def lockdir(mydir): return lockfile(mydir,wantnewlockfile=1) -- 2.26.2