summaryrefslogtreecommitdiff
path: root/indra/viewer_components/updater/scripts/darwin/update_install.py
diff options
context:
space:
mode:
Diffstat (limited to 'indra/viewer_components/updater/scripts/darwin/update_install.py')
-rwxr-xr-xindra/viewer_components/updater/scripts/darwin/update_install.py49
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