[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):
log.info("Deluge daemon shutting down, waiting for components to shutdown...")
return component.shutdown()
if not self.classic:
return component.shutdown()
@export()
def get_method_list(self):

View File

@ -13,12 +13,13 @@ from __future__ import division
import logging
import os
import signal
import sys
import time
import gobject
import gtk
from twisted.internet import gtk2reactor
from twisted.internet import defer, gtk2reactor
from twisted.internet.error import ReactorAlreadyInstalledError
from twisted.internet.task import LoopingCall
@ -251,36 +252,48 @@ class GtkUI(object):
self.rpc_stats = LoopingCall(self.print_rpc_stats)
# 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)
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
gtk.gdk.threads_enter()
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()
def shutdown(self, *args, **kwargs):
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)
log.debug("GTKUI shutting down...")
# 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.
self.config.save()
def pre_shutdown(self, *args, **kwargs):
"""Modal dialogs can prevent the application exiting so destroy mainwindow"""
# Ensure columns state is saved
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()
reactor.stop()
def print_rpc_stats(self):
if not client.connected():
return

View File

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