From: robk-tahoe Date: Thu, 6 Mar 2008 20:53:21 +0000 (-0700) Subject: macapp: report failure of node startup to the user X-Git-Tag: allmydata-tahoe-0.9.0~58 X-Git-Url: https://git.rkrishnan.org/banana.xhtml?a=commitdiff_plain;h=ee67d788cde64c9ecdb07d05a7b57fb23d227045;p=tahoe-lafs%2Ftahoe-lafs.git macapp: report failure of node startup to the user in certain cases (e.g. the node.pem changed but old .furls are in private/) the node will abort upon startup. previously it used os.abort() which in these cases caused the mac gui app to crash on startup with no explanation. this changes that behaviour from calling os.abort() to calling node._abort_process(failure) which by default calls os.abort(). this allows that method to be overridden in subclasses. the mac app now provides and uses such a subclass of Client, so that failures are reported to the user in a message dialog before the process exits. this uses wx.PostEvent() with a custom event type to signal from the reactor thread into the gui thread. --- diff --git a/src/allmydata/gui/macapp.py b/src/allmydata/gui/macapp.py index 58b470a3..34176b64 100644 --- a/src/allmydata/gui/macapp.py +++ b/src/allmydata/gui/macapp.py @@ -43,6 +43,23 @@ def run_macapp(): app = App(basedir) return app.run() +ABORT_EVENT_ID = wx.NewId() + +class AbortEvent(wx.PyEvent): + def __init__(self, failure): + wx.PyEvent.__init__(self) + self.SetEventType(ABORT_EVENT_ID) + self.failure = failure + +class MacGuiClient(client.Client): + def __init__(self, basedir, app): + self.app = app + client.Client.__init__(self, basedir) + + def _abort_process(self, failure): + event = AbortEvent(failure) + wx.PostEvent(self.app.guiapp.frame, event) + class App(object): def __init__(self, basedir): self.basedir = basedir @@ -89,8 +106,8 @@ class App(object): self.start_reactor() try: - guiapp = MacGuiApp(app=self) - guiapp.MainLoop() + self.guiapp = MacGuiApp(app=self) + self.guiapp.MainLoop() log.msg('gui mainloop exited') except: log.err() @@ -105,7 +122,8 @@ class App(object): def launch_reactor(self): # run the node itself - c = client.Client(self.basedir) + #c = client.Client(self.basedir) + c = MacGuiClient(self.basedir, self) reactor.callLater(0, c.startService) # after reactor startup reactor.run(installSignalHandlers=False) self.reactor_shutdown.set() @@ -176,8 +194,9 @@ ACCOUNT_PAGE_ID = wx.NewId() MOUNT_ID = wx.NewId() class SplashFrame(wx.Frame): - def __init__(self): + def __init__(self, app): wx.Frame.__init__(self, None, -1, 'Allmydata Tahoe') + self.app = app self.SetSizeHints(100, 100, 600, 800) self.SetIcon(amdicon.getIcon()) @@ -196,9 +215,16 @@ class SplashFrame(wx.Frame): self.Fit() self.Layout() + # plumb up event handler for abort + self.Connect(-1, -1, ABORT_EVENT_ID, self.wx_abort) + def on_close(self, event): self.Show(False) + def wx_abort(self, event): + wx.MessageBox(event.failure.getTraceback(), 'Fatal Error in Node startup') + self.app.ExitMainLoop() + class SplashPanel(wx.Panel): def __init__(self, parent, on_close): wx.Panel.__init__(self, parent, -1) @@ -369,7 +395,7 @@ class MacGuiApp(wx.App): def OnInit(self): try: - self.frame = SplashFrame() + self.frame = SplashFrame(self) self.frame.Show(True) self.SetTopWindow(self.frame) diff --git a/src/allmydata/node.py b/src/allmydata/node.py index ae1f9229..5ce189ec 100644 --- a/src/allmydata/node.py +++ b/src/allmydata/node.py @@ -172,11 +172,15 @@ class Node(service.MultiService): print "Node._startService failed, aborting" print failure #reactor.stop() # for unknown reasons, reactor.stop() isn't working. [ ] TODO - self.log('calling os.abort()') - print "calling os.abort()" - os.abort() + self._abort_process(failure) d.addErrback(_die) + def _abort_process(self, failure): + self.log('calling os.abort()') + log('calling os.abort()') + print "calling os.abort()" + os.abort() + def stopService(self): self.log("Node.stopService") d = self._tub_ready_observerlist.when_fired()