mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix regression in 0.8.33 that caused calibre to crash when starting the Content Server, if the port the content server is trying to listen on is blocked/busy. Fixes #910512 (calibre crashs after start without message)
This commit is contained in:
parent
87c2406cd8
commit
b117148241
@ -63,16 +63,21 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
|
||||
def start_server(self):
|
||||
ConfigWidgetBase.commit(self)
|
||||
self.gui.start_content_server(check_started=False)
|
||||
while not self.gui.content_server.is_running and self.gui.content_server.exception is None:
|
||||
time.sleep(1)
|
||||
if self.gui.content_server.exception is not None:
|
||||
error_dialog(self, _('Failed to start content server'),
|
||||
as_unicode(self.gui.content_server.exception)).exec_()
|
||||
return
|
||||
self.start_button.setEnabled(False)
|
||||
self.test_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(True)
|
||||
self.setCursor(Qt.BusyCursor)
|
||||
try:
|
||||
self.gui.start_content_server(check_started=False)
|
||||
while (not self.gui.content_server.is_running and
|
||||
self.gui.content_server.exception is None):
|
||||
time.sleep(0.1)
|
||||
if self.gui.content_server.exception is not None:
|
||||
error_dialog(self, _('Failed to start content server'),
|
||||
as_unicode(self.gui.content_server.exception)).exec_()
|
||||
return
|
||||
self.start_button.setEnabled(False)
|
||||
self.test_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(True)
|
||||
finally:
|
||||
self.unsetCursor()
|
||||
|
||||
def stop_server(self):
|
||||
self.gui.content_server.threaded_exit()
|
||||
|
@ -368,9 +368,14 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
self.library_view.model().db, server_config().parse())
|
||||
self.content_server.state_callback = Dispatcher(
|
||||
self.iactions['Connect Share'].content_server_state_changed)
|
||||
self.content_server.state_callback(True)
|
||||
if check_started:
|
||||
QTimer.singleShot(10000, self.test_server)
|
||||
self.content_server.start_failure_callback = \
|
||||
Dispatcher(self.content_server_start_failed)
|
||||
|
||||
def content_server_start_failed(self, msg):
|
||||
error_dialog(self, _('Failed to start Content Server'),
|
||||
_('Could not start the content server. Error:\n\n%s')%msg,
|
||||
show=True)
|
||||
|
||||
def resizeEvent(self, ev):
|
||||
MainWindow.resizeEvent(self, ev)
|
||||
|
@ -26,7 +26,7 @@ from calibre.library.server.cache import Cache
|
||||
from calibre.library.server.browse import BrowseServer
|
||||
from calibre.library.server.ajax import AjaxServer
|
||||
from calibre.utils.search_query_parser import saved_searches
|
||||
from calibre import prints
|
||||
from calibre import prints, as_unicode
|
||||
|
||||
|
||||
class DispatchController(object): # {{{
|
||||
@ -112,6 +112,7 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache,
|
||||
self.opts = opts
|
||||
self.embedded = embedded
|
||||
self.state_callback = None
|
||||
self.start_failure_callback = None
|
||||
try:
|
||||
self.max_cover_width, self.max_cover_height = \
|
||||
map(int, self.opts.max_cover.split('x'))
|
||||
@ -225,41 +226,57 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache,
|
||||
h.setFormatter(cherrypy._cplogging.logfmt)
|
||||
log.access_log.addHandler(h)
|
||||
|
||||
def start_cherrypy(self):
|
||||
try:
|
||||
cherrypy.engine.start()
|
||||
except:
|
||||
ip = get_external_ip()
|
||||
if not ip or ip.startswith('127.'):
|
||||
raise
|
||||
cherrypy.log('Trying to bind to single interface: '+ip)
|
||||
# Change the host we listen on
|
||||
cherrypy.config.update({'server.socket_host' : ip})
|
||||
# This ensures that the change is actually applied
|
||||
cherrypy.server.socket_host = ip
|
||||
cherrypy.server.httpserver = cherrypy.server.instance = None
|
||||
|
||||
cherrypy.engine.start()
|
||||
|
||||
def start(self):
|
||||
self.is_running = False
|
||||
self.exception = None
|
||||
cherrypy.tree.mount(root=None, config=self.config)
|
||||
try:
|
||||
try:
|
||||
cherrypy.engine.start()
|
||||
except:
|
||||
ip = get_external_ip()
|
||||
if not ip or ip.startswith('127.'):
|
||||
raise
|
||||
cherrypy.log('Trying to bind to single interface: '+ip)
|
||||
# Change the host we listen on
|
||||
cherrypy.config.update({'server.socket_host' : ip})
|
||||
# This ensures that the change is actually applied
|
||||
cherrypy.server.socket_host = ip
|
||||
cherrypy.server.httpserver = cherrypy.server.instance = None
|
||||
|
||||
cherrypy.engine.start()
|
||||
|
||||
self.is_running = True
|
||||
#if hasattr(cherrypy.engine, 'signal_handler'):
|
||||
# cherrypy.engine.signal_handler.subscribe()
|
||||
|
||||
cherrypy.engine.block()
|
||||
self.start_cherrypy()
|
||||
except Exception as e:
|
||||
self.exception = e
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
if callable(self.start_failure_callback):
|
||||
try:
|
||||
self.start_failure_callback(as_unicode(e))
|
||||
except:
|
||||
pass
|
||||
return
|
||||
|
||||
try:
|
||||
self.is_running = True
|
||||
self.notify_listener()
|
||||
cherrypy.engine.block()
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
self.exception = e
|
||||
finally:
|
||||
self.is_running = False
|
||||
try:
|
||||
if callable(self.state_callback):
|
||||
self.state_callback(self.is_running)
|
||||
except:
|
||||
pass
|
||||
self.notify_listener()
|
||||
|
||||
def notify_listener(self):
|
||||
try:
|
||||
if callable(self.state_callback):
|
||||
self.state_callback(self.is_running)
|
||||
except:
|
||||
pass
|
||||
|
||||
def exit(self):
|
||||
try:
|
||||
@ -267,11 +284,7 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache,
|
||||
finally:
|
||||
cherrypy.server.httpserver = None
|
||||
self.is_running = False
|
||||
try:
|
||||
if callable(self.state_callback):
|
||||
self.state_callback(self.is_running)
|
||||
except:
|
||||
pass
|
||||
self.notify_listener()
|
||||
|
||||
def threaded_exit(self):
|
||||
from threading import Thread
|
||||
|
@ -268,7 +268,11 @@ class Bus(object):
|
||||
# Assume it's been logged and just die.
|
||||
os._exit(70) # EX_SOFTWARE
|
||||
|
||||
if exitstate == states.STARTING:
|
||||
# Changed by Kovid, we cannot have all of calibre being quit
|
||||
# Also we want to catch the port blocked/busy error and try listening only on
|
||||
# the external ip
|
||||
# See https://bitbucket.org/cherrypy/cherrypy/issue/1017/exit-behavior-is-not-good-when-running-in
|
||||
if False and exitstate == states.STARTING:
|
||||
# exit() was called before start() finished, possibly due to
|
||||
# Ctrl-C because a start listener got stuck. In this case,
|
||||
# we could get stuck in a loop where Ctrl-C never exits the
|
||||
|
Loading…
x
Reference in New Issue
Block a user