diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 715696a89e..7bd836009f 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -99,6 +99,7 @@ gprefs.defaults['book_display_fields'] = [ gprefs.defaults['default_author_link'] = 'http://en.wikipedia.org/w/index.php?search={author}' gprefs.defaults['preserve_date_on_ctl'] = True gprefs.defaults['cb_fullscreen'] = False +gprefs.defaults['worker_max_time'] = 0 # }}} diff --git a/src/calibre/gui2/jobs.py b/src/calibre/gui2/jobs.py index c9277518e2..076a9720a3 100644 --- a/src/calibre/gui2/jobs.py +++ b/src/calibre/gui2/jobs.py @@ -181,6 +181,20 @@ class JobManager(QAbstractTableModel): # {{{ self.dataChanged.emit( self.index(idx, 0), self.index(idx, 3)) + # Kill parallel jobs that have gone on too long + try: + wmax_time = gprefs['worker_max_time'] * 60 + except: + wmax_time = 0 + + if wmax_time > 0: + for job in self.jobs: + if isinstance(job, ParallelJob): + rtime = job.running_time + if (rtime is not None and rtime > wmax_time and + job.duration is None): + job.timed_out = True + self.server.kill_job(job) def _add_job(self, job): self.layoutAboutToBeChanged.emit() diff --git a/src/calibre/gui2/preferences/misc.py b/src/calibre/gui2/preferences/misc.py index 60a4540b99..fcab1b4958 100644 --- a/src/calibre/gui2/preferences/misc.py +++ b/src/calibre/gui2/preferences/misc.py @@ -8,7 +8,8 @@ __docformat__ = 'restructuredtext en' from calibre.gui2.preferences import ConfigWidgetBase, test_widget, Setting from calibre.gui2.preferences.misc_ui import Ui_Form -from calibre.gui2 import error_dialog, config, open_local_file, info_dialog +from calibre.gui2 import (error_dialog, config, open_local_file, info_dialog, + gprefs) from calibre.constants import isosx from calibre import get_proxies @@ -29,6 +30,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): r = self.register r('worker_limit', config, restart_required=True, setting=WorkersSetting) r('enforce_cpu_limit', config, restart_required=True) + r('worker_max_time', gprefs) self.device_detection_button.clicked.connect(self.debug_device_detection) self.button_open_config_dir.clicked.connect(self.open_config_dir) self.user_defined_device_button.clicked.connect(self.user_defined_device) diff --git a/src/calibre/gui2/preferences/misc.ui b/src/calibre/gui2/preferences/misc.ui index dd9b984d48..1b4f0a1658 100644 --- a/src/calibre/gui2/preferences/misc.ui +++ b/src/calibre/gui2/preferences/misc.ui @@ -51,21 +51,21 @@ - + Debug &device detection - + Get information to setup the &user defined device - + Qt::Vertical @@ -78,7 +78,7 @@ - + Qt::Vertical @@ -91,14 +91,14 @@ - + Open calibre &configuration directory - + Qt::Vertical @@ -111,14 +111,14 @@ - + &Install command line tools - + Qt::Vertical @@ -131,13 +131,39 @@ - + + + + + &Abort conversion jobs that take more than: + + + opt_worker_max_time + + + + + + + Never abort + + + minutes + + + 100000 + + + 10 + + + diff --git a/src/calibre/utils/ipc/job.py b/src/calibre/utils/ipc/job.py index e75884d387..d99f2ae792 100644 --- a/src/calibre/utils/ipc/job.py +++ b/src/calibre/utils/ipc/job.py @@ -43,13 +43,17 @@ class BaseJob(object): self._status_text = _('Waiting...') self._done_called = False self.core_usage = 1 + self.timed_out = False def update(self, consume_notifications=True): if self.duration is not None: self._run_state = self.FINISHED self.percent = 100 if self.killed: - self._status_text = _('Stopped') + if self.timed_out: + self._status_text = _('Aborted, taking too long') + else: + self._status_text = _('Stopped') else: self._status_text = _('Error') if self.failed else _('Finished') if DEBUG: