diff --git a/ChangeLog b/ChangeLog index b6c2450..d1b14e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-05-07 Thomas Vander Stichele + + * morituri/common/task.py: + Log on runners too. + * morituri/program/cdrdao.py: + Abort if output has ERROR by killing and setting an exception. + 2009-05-07 Thomas Vander Stichele * examples/readdisc.py: diff --git a/morituri/common/task.py b/morituri/common/task.py index f85eca6..b14dd5c 100644 --- a/morituri/common/task.py +++ b/morituri/common/task.py @@ -216,11 +216,12 @@ class MultiCombinedTask(BaseMultiTask): self.setProgress(float(self._stopped) / len(self.tasks)) BaseMultiTask.stopped(self, task) -class TaskRunner(object): +class TaskRunner(object, log.Loggable): """ I am a base class for task runners. Task runners should be reusable. """ + logCategory = 'TaskRunner' def run(self, task): """ @@ -279,6 +280,7 @@ class SyncRunner(TaskRunner): self._longest = 0 # longest string shown; for clearing def run(self, task, verbose=None, skip=False): + self.debug('run task %r', task) self._task = task self._verboseRun = self._verbose if verbose is not None: @@ -291,7 +293,9 @@ class SyncRunner(TaskRunner): # otherwise the task might complete before we are in it gobject.timeout_add(0L, self._task.start, self) self._loop.run() + self.debug('done running task %r', task) if self._task.exception: + self.debug('raising exception') raise self._task.exception def schedule(self, delta, callable, *args, **kwargs): diff --git a/morituri/program/cdrdao.py b/morituri/program/cdrdao.py index ac33d39..a21546d 100644 --- a/morituri/program/cdrdao.py +++ b/morituri/program/cdrdao.py @@ -23,6 +23,7 @@ import re import os +import signal import subprocess import tempfile @@ -30,6 +31,14 @@ from morituri.common import task, log from morituri.image import toc, table from morituri.extern import asyncsub +class ProgramError(Exception): + """ + The program had a fatal error. + """ + def __init__(self, message): + self.args = (message, ) + self.message = message + states = ['START', 'TRACK', 'LEADOUT', 'DONE'] _ANALYZING_RE = re.compile(r'^Analyzing track (?P\d+).*') @@ -118,7 +127,9 @@ class OutputParser(object, log.Loggable): for line in lines: self.log('Parsing %s', line) if line.startswith('ERROR:'): - self._errors.append(line) + self._task.exception = ProgramError(line) + self._task.abort() + return self._parse(lines) self._lines.extend(lines) @@ -191,6 +202,7 @@ class CDRDAOTask(task.Task): bufsize=bufsize, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) + self.debug('Started cdrdao with pid %d', self._popen.pid) self.runner.schedule(1.0, self._read, runner) @@ -221,6 +233,11 @@ class CDRDAOTask(task.Task): self.stop() return + def abort(self): + self.debug('Aborting, sending SIGTERM to %d', self._popen.pid) + os.kill(self._popen.pid, signal.SIGTERM) + self.stop() + def readbytes(self, bytes): """ Called when bytes have been read from stderr.