From ab7b331aac34b82d436258aa201a34ca39f6cf9b Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Sun, 14 Dec 2008 18:31:24 -0500 Subject: [PATCH] Make client survive the daemon going down. Port a few fixes from trunk. --- wicd/gui.py | 36 ++++++++++++++++++-------- wicd/misc.py | 12 ++++++--- wicd/wicd-client.py | 62 ++++++++++++++++++++++++++++----------------- wicd/wicd-daemon.py | 14 +++++----- 4 files changed, 81 insertions(+), 43 deletions(-) diff --git a/wicd/gui.py b/wicd/gui.py index 6b69fea..f42539d 100644 --- a/wicd/gui.py +++ b/wicd/gui.py @@ -53,20 +53,24 @@ except: proxy_obj = daemon = wireless = wired = bus = None language = misc.get_language_list_gui() -def setup_dbus(): +def setup_dbus(force=True): global bus, daemon, wireless, wired try: dbusmanager.connect_to_dbus() except DBusException: - print "Can't connect to the daemon, trying to start it automatically..." - misc.PromptToStartDaemon() - try: - dbusmanager.connect_to_dbus() - except DBusException: - error(None, "Could not connect to wicd's D-Bus interface. " + - "Make sure the daemon is started.") - sys.exit(1) + if force: + print "Can't connect to the daemon, trying to start it automatically..." + misc.PromptToStartDaemon() + try: + dbusmanager.connect_to_dbus() + except DBusException: + error(None, "Could not connect to wicd's D-Bus interface. " + + "Check the wicd log for error messages.") + return False + else: + return False + bus = dbusmanager.get_bus() dbus_ifaces = dbusmanager.get_dbus_ifaces() @@ -75,6 +79,16 @@ def setup_dbus(): wired = dbus_ifaces['wired'] return True + +@misc.threaded +def handle_no_dbus(): + print "Wicd daemon is shutting down!" + error(None, "The wicd daemon has shut down, the UI will not function properly until it is restarted.") + while True: + time.sleep(10) + print "Trying to reconnect.." + if not setup_dbus(force=False): + print "Failed to reconnect to the daemon." def error(parent, message): """ Shows an error dialog """ @@ -277,7 +291,9 @@ class appGui(object): 'org.wicd.daemon.wireless') bus.add_signal_receiver(self.update_connect_buttons, 'StatusChanged', 'org.wicd.daemon') - bus.add_signal_receiver(setup_dbus, "DaemonClosing", "org.wicd.daemon") + if standalone: + bus.add_signal_receiver(handle_no_dbus, "DaemonClosing", + "org.wicd.daemon") try: gobject.timeout_add_seconds(1, self.update_statusbar) except: diff --git a/wicd/misc.py b/wicd/misc.py index 2c46ec1..b7ef6df 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -69,7 +69,7 @@ def Run(cmd, include_stderr=False, return_pipe=False): one output string from the command. """ - if type(cmd) is not list: + if not isinstance(cmd, list): cmd = to_unicode(str(cmd)) cmd = cmd.split() if include_stderr: @@ -82,8 +82,12 @@ def Run(cmd, include_stderr=False, return_pipe=False): tmpenv = os.environ.copy() tmpenv["LC_ALL"] = "C" tmpenv["LANG"] = "C" - f = Popen(cmd, shell=False, stdout=PIPE, stderr=err, close_fds=fds, cwd='/', - env=tmpenv) + try: + f = Popen(cmd, shell=False, stdout=PIPE, stderr=err, close_fds=fds, + cwd='/', env=tmpenv) + except OSError, e: + print "Running command %s failed: %s" % (str(cmd), str(e)) + return "" if return_pipe: return f.stdout @@ -383,7 +387,7 @@ def find_path(cmd): the file can not be found. """ - paths = os.getenv("PATH", default=["/usr/bin", "/usr/local/bin"]).split(':') + paths = os.getenv("PATH", default="/usr/bin:/usr/local/bin").split(':') for path in paths: if os.access(os.path.join(path, cmd), os.F_OK): return os.path.join(path, cmd) diff --git a/wicd/wicd-client.py b/wicd/wicd-client.py index c403141..5993b55 100755 --- a/wicd/wicd-client.py +++ b/wicd/wicd-client.py @@ -59,7 +59,7 @@ if not hasattr(gtk, "StatusIcon"): import egg.trayicon USE_EGG = True except ImportError: - print 'Unable to load tray icon: Missing egg.trayicon module.' + print 'Unable to load tray icon: Missing both egg.trayicon and gtk.StatusIcon modules.' ICON_AVAIL = False misc.RenameProcess("wicd-client") @@ -125,7 +125,10 @@ class TrayIcon(object): self.max_snd_gain = 10000 self.max_rcv_gain = 10000 self.animate = animate - self.update_tray_icon() + if DBUS_AVAIL: + self.update_tray_icon() + else: + handle_no_dbus() def wired_profile_chooser(self): """ Launch the wired profile chooser. """ @@ -349,15 +352,6 @@ class TrayIcon(object): """ Callback for when a wireless scan finishes. """ self._is_scanning = False self.populate_network_menu() - - def dbus_lost(self): - """ Callback for when the daemon is going down. """ - global DBUS_AVAIL - print "The daemon is going down!!" - DBUS_AVAIL = False - time.sleep(1) - while not setup_dbus(): - time.sleep(20) def on_activate(self, data=None): """ Opens the wicd GUI. """ @@ -638,26 +632,49 @@ Arguments: \t-a\t--no-animate\tRun the tray without network traffic tray animations. """ -def setup_dbus(): - global daemon, wireless, wired, DBUS_AVAIL +def setup_dbus(force=True): + global bus, daemon, wireless, wired, DBUS_AVAIL try: dbusmanager.connect_to_dbus() except DBusException: - print "Can't connect to the daemon, trying to start it automatically..." - misc.PromptToStartDaemon() - try: - dbusmanager.connect_to_dbus() - except DBusException: - gui.error(None, language['cannot_start_daemon']) - sys.exit(1) + if force: + print "Can't connect to the daemon, trying to start it automatically..." + misc.PromptToStartDaemon() + try: + dbusmanager.connect_to_dbus() + except DBusException: + gui.error(None, "Could not connect to wicd's D-Bus interface. " + + "Check the wicd log for error messages.") + return False + else: + return False + + bus = dbusmanager.get_bus() dbus_ifaces = dbusmanager.get_dbus_ifaces() daemon = dbus_ifaces['daemon'] wireless = dbus_ifaces['wireless'] wired = dbus_ifaces['wired'] DBUS_AVAIL = True + return True +@misc.threaded +def handle_no_dbus(): + global DBUS_AVAIL + print "Wicd daemon is shutting down!" + gui.error(None, "The wicd daemon has shut down, the UI will not function " + + "properly until it is restarted.") + while True: + time.sleep(10) + print "Trying to reconnect.." + if not setup_dbus(force=False): + print "Failed to reconnect to the daemon." + else: + gui.setup_dbus(force=False) + DBUS_AVAIL = True + return True + def main(argv): """ The main frontend program. @@ -702,7 +719,7 @@ def main(argv): # Check to see if wired profile chooser was called before icon # was launched (typically happens on startup or daemon restart). - if daemon.GetNeedWiredProfileChooser(): + if DBUS_AVAIL and daemon.GetNeedWiredProfileChooser(): daemon.SetNeedWiredProfileChooser(False) tray_icon.icon_info.wired_profile_chooser() @@ -715,8 +732,7 @@ def main(argv): 'org.wicd.daemon.wireless') bus.add_signal_receiver(tray_icon.tr.tray_scan_started, 'SendStartScanSignal', 'org.wicd.daemon.wireless') - bus.add_signal_receiver(tray_icon.tr.dbus_lost, - "DaemonClosing", 'org.wicd.daemon') + bus.add_signal_receiver(handle_no_dbus, "DaemonClosing", 'org.wicd.daemon') print 'Done.' mainloop = gobject.MainLoop() mainloop.run() diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index 87b6ab3..5d3ee1b 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -1540,10 +1540,11 @@ def main(argv): daemon = WicdDaemon(wicd_bus, auto_connect=auto_connect) gobject.threads_init() if not no_poll: - (child_pid, x, x, x) = gobject.spawn_async(["/usr/bin/python", "-O", - wpath.lib + "monitor.py"], - flags=gobject.SPAWN_CHILD_INHERITS_STDIN) - signal.signal(signal.SIGTERM, sigterm_caught) + (child_pid, x, x, x) = gobject.spawn_async( + [misc.find_path("python"), "-O", os.path.join(wpath.lib, "monitor.py")], + flags=gobject.SPAWN_CHILD_INHERITS_STDIN + ) + signal.signal(signal.SIGTERM, sigterm_caught) # Enter the main loop mainloop = gobject.MainLoop() @@ -1557,8 +1558,9 @@ def main(argv): def sigterm_caught(sig=None, frame=None): """ Called when a SIGTERM is caught, kills monitor.py before exiting. """ global child_pid - print 'Daemon going down, killing wicd-monitor...' - os.kill(child_pid, signal.SIGTERM) + if child_pid: + print 'Daemon going down, killing wicd-monitor...' + os.kill(child_pid, signal.SIGTERM) print 'Removing PID file...' if os.path.exists(wpath.pidfile): os.remove(wpath.pidfile)