diff options
Diffstat (limited to 'indra/viewer_components/updater/scripts/darwin/update_install.py')
-rwxr-xr-x | indra/viewer_components/updater/scripts/darwin/update_install.py | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py index 2fc6fcdb29..08f4f0ebb9 100755 --- a/indra/viewer_components/updater/scripts/darwin/update_install.py +++ b/indra/viewer_components/updater/scripts/darwin/update_install.py @@ -17,6 +17,7 @@ $/LicenseInfo$ import os import sys import cgitb +from contextlib import contextmanager import errno import glob import plistlib @@ -32,6 +33,11 @@ import Tkinter, tkMessageBox TITLE = "Second Life Viewer Updater" # Magic bundle identifier used by all Second Life viewer bundles BUNDLE_IDENTIFIER = "com.secondlife.indra.viewer" +# Magic OS directory name that causes Cocoa viewer to crash on OS X 10.7.5 +# (see MAINT-3331) +STATE_DIR = os.path.join( + os.environ["HOME"], "Library", "Saved Application State", + BUNDLE_IDENTIFIER + ".savedState") # Global handle to the MessageFrame so we can update message FRAME = None @@ -137,6 +143,23 @@ def write_marker(markerfile, markertext): log("%s exception: %s" % (err.__class__.__name__, err)) # **************************************************************************** +# Utility +# **************************************************************************** +@contextmanager +def allow_errno(errn): + """ + Execute body of 'with' statement, accepting OSError with specific errno + 'errn'. Propagate any other exception, or an OSError with any other errno. + """ + try: + # run the body of the 'with' statement + yield + except OSError, err: + # unless errno == passed errn, re-raise the exception + if err.errno != errn: + raise + +# **************************************************************************** # Main script logic # **************************************************************************** def main(dmgfile, markerfile, markertext): @@ -158,12 +181,9 @@ def main(dmgfile, markerfile, markertext): # Move the old updater.log file out of the way logname = os.path.join(logsdir, "updater.log") - try: + # Nonexistence is okay. Anything else, not so much. + with allow_errno(errno.ENOENT): os.rename(logname, logname + ".old") - except OSError, err: - # Nonexistence is okay. Anything else, not so much. - if err.errno != errno.ENOENT: - raise # Open new updater.log. global LOGF @@ -179,6 +199,11 @@ def main(dmgfile, markerfile, markertext): # prepare for other cleanup with Janitor(LOGF) as janitor: + # Under some circumstances, this script seems to be invoked with a + # nonexistent pathname. Check for that. + if not os.path.isfile(dmgfile): + fail(dmgfile + " has been deleted") + # Try to derive the name of the running viewer app bundle from our # own pathname. (Hopefully the old viewer won't copy this script # to a temp dir before running!) @@ -345,10 +370,24 @@ def main(dmgfile, markerfile, markertext): log("touch " + appdir) os.utime(appdir, None) # set to current time + # MAINT-3331: remove STATE_DIR. Empirically, this resolves a + # persistent, mysterious crash after updating our viewer on an OS + # X 10.7.5 system. + log("rm -rf '%s'" % STATE_DIR) + with allow_errno(errno.ENOENT): + shutil.rmtree(STATE_DIR) + command = ["open", appdir] log(' '.join(command)) subprocess.check_call(command, stdout=LOGF, stderr=subprocess.STDOUT) + # If all the above succeeded, delete the .dmg file. We don't do this + # as a janitor.later() operation because we only want to do it if we + # get this far successfully. Note that this is out of the scope of the + # Janitor: we must detach the .dmg before removing it! + log("rm " + dmgfile) + os.remove(dmgfile) + except Exception, err: # Because we carefully set sys.excepthook -- and even modify it to log # the problem once we have our log file open -- you might think we |