[GTKUI] Fix #2802: GTKUI classic mode shutdown procedure is broken

Fix by leaving shutdown procedure to gtkui.py:
* Daemon no longer calls component.shutdown() in GTKUI classic mode
* Mainwindow no longer calls reactor.stop but instead fires a
  'gtkui_close' signal.
* gtkui.py installs custom SIGINT handler to initiate shutdown before
  stopping reactor.
This commit is contained in:
bendikro 2016-04-14 22:29:37 +02:00 committed by Calum Lind
parent 70d8b65f0a
commit 47f14845ca
3 changed files with 31 additions and 17 deletions

View File

@ -154,7 +154,8 @@ class Daemon(object):
def _shutdown(self, *args, **kwargs): def _shutdown(self, *args, **kwargs):
log.info("Deluge daemon shutting down, waiting for components to shutdown...") log.info("Deluge daemon shutting down, waiting for components to shutdown...")
return component.shutdown() if not self.classic:
return component.shutdown()
@export() @export()
def get_method_list(self): def get_method_list(self):

View File

@ -13,12 +13,13 @@ from __future__ import division
import logging import logging
import os import os
import signal
import sys import sys
import time import time
import gobject import gobject
import gtk import gtk
from twisted.internet import gtk2reactor from twisted.internet import defer, gtk2reactor
from twisted.internet.error import ReactorAlreadyInstalledError from twisted.internet.error import ReactorAlreadyInstalledError
from twisted.internet.task import LoopingCall from twisted.internet.task import LoopingCall
@ -251,36 +252,48 @@ class GtkUI(object):
self.rpc_stats = LoopingCall(self.print_rpc_stats) self.rpc_stats = LoopingCall(self.print_rpc_stats)
# Twisted catches signals to terminate, so have it call a pre_shutdown method. # Twisted catches signals to terminate, so have it call a pre_shutdown method.
reactor.addSystemEventTrigger("before", "shutdown", self.pre_shutdown) reactor.addSystemEventTrigger("before", "gtkui_close", self.close)
reactor.callWhenRunning(self._on_reactor_start) reactor.callWhenRunning(self._on_reactor_start)
self.closing = False
def gtkui_sigint_handler(num, frame):
log.debug("SIGINT signal caught - firing event: 'gtkui_close'")
reactor.callLater(0, reactor.fireSystemEvent, 'gtkui_close')
signal.signal(signal.SIGINT, gtkui_sigint_handler)
# Initialize gdk threading # Initialize gdk threading
gtk.gdk.threads_enter() gtk.gdk.threads_enter()
reactor.run() reactor.run()
self.shutdown() # Reactor is not running. Any async callbacks (Deferreds) can no longer
# be processed from this point on.
gtk.gdk.threads_leave() gtk.gdk.threads_leave()
def shutdown(self, *args, **kwargs): def shutdown(self, *args, **kwargs):
log.debug("gtkui shutting down..") log.debug("GTKUI shutting down...")
component.stop()
# Process any pending gtk events since the mainloop has been quit
while gtk.events_pending():
gtk.main_iteration(0)
# Shutdown all components # Shutdown all components
component.shutdown() if self.started_in_classic:
return component.shutdown()
@defer.inlineCallbacks
def close(self):
if self.closing:
return
self.closing = True
# Make sure the config is saved. # Make sure the config is saved.
self.config.save() self.config.save()
def pre_shutdown(self, *args, **kwargs):
"""Modal dialogs can prevent the application exiting so destroy mainwindow"""
# Ensure columns state is saved # Ensure columns state is saved
self.torrentview.save_state() self.torrentview.save_state()
# Shut down components
yield self.shutdown()
# Modal dialogs can prevent the application exiting so destroy mainwindow
# Must do this here to avoid hang when closing with SIGINT (CTRL-C)
self.mainwindow.window.destroy() self.mainwindow.window.destroy()
reactor.stop()
def print_rpc_stats(self): def print_rpc_stats(self):
if not client.connected(): if not client.connected():
return return

View File

@ -215,7 +215,7 @@ class MainWindow(component.Component):
def quit_gtkui(): def quit_gtkui():
def stop_gtk_reactor(result=None): def stop_gtk_reactor(result=None):
try: try:
reactor.stop() reactor.callLater(0, reactor.fireSystemEvent, 'gtkui_close')
except ReactorNotRunning: except ReactorNotRunning:
log.debug("Attempted to stop the reactor but it is not running...") log.debug("Attempted to stop the reactor but it is not running...")