* morituri/program/cdparanoia.py:
cdparanoia can hang indefinitely on scsi read errors. For example, on some drives, when trying negative offsets. Notice them, count them, and fail after 100. * morituri/test/test_program_cdparanoia.py: * morituri/test/cdparanoia.progress.error (added): Add a test for this output.
This commit is contained in:
16
ChangeLog
16
ChangeLog
@@ -1,3 +1,19 @@
|
||||
2011-03-23 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* morituri/program/cdparanoia.py:
|
||||
cdparanoia can hang indefinitely on scsi read errors.
|
||||
For example, on some drives, when trying negative offsets.
|
||||
Notice them, count them, and fail after 100.
|
||||
* morituri/test/test_program_cdparanoia.py:
|
||||
* morituri/test/cdparanoia.progress.error (added):
|
||||
Add a test for this output.
|
||||
|
||||
2011-03-23 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* morituri/program/cdparanoia.py:
|
||||
* morituri/test/test_program_cdparanoia.py:
|
||||
|
||||
|
||||
2011-03-22 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* morituri/common/program.py:
|
||||
|
||||
@@ -31,6 +31,9 @@ from morituri.common import task, log, common
|
||||
from morituri.extern import asyncsub
|
||||
|
||||
class FileSizeError(Exception):
|
||||
|
||||
message = None
|
||||
|
||||
"""
|
||||
The given path does not have the expected size.
|
||||
"""
|
||||
@@ -53,12 +56,15 @@ _PROGRESS_RE = re.compile(r"""
|
||||
(?P<offset>\d+) # offset
|
||||
""", re.VERBOSE)
|
||||
|
||||
_ERROR_RE = re.compile("^scsi_read error:")
|
||||
|
||||
# from reading cdparanoia source code, it looks like offset is reported in
|
||||
# number of single-channel samples, ie. 2 bytes per unit, and absolute
|
||||
|
||||
class ProgressParser(object):
|
||||
read = 0 # last [read] frame
|
||||
wrote = 0 # last [wrote] frame
|
||||
errors = 0 # count of number of scsi errors
|
||||
_nframes = None # number of frames read on each [read]
|
||||
_firstFrames = None # number of frames read on first [read]
|
||||
reads = 0 # total number of reads
|
||||
@@ -93,6 +99,10 @@ class ProgressParser(object):
|
||||
elif function == 'wrote':
|
||||
self._parse_wrote(wordOffset)
|
||||
|
||||
m = _ERROR_RE.search(line)
|
||||
if m:
|
||||
self.errors += 1
|
||||
|
||||
def _parse_read(self, wordOffset):
|
||||
if wordOffset % common.WORDS_PER_FRAME != 0:
|
||||
print 'THOMAS: not a multiple of %d: %d' % (
|
||||
@@ -180,6 +190,8 @@ class ReadTrackTask(task.Task):
|
||||
description = "Reading Track"
|
||||
quality = None # set at end of reading
|
||||
|
||||
_MAXERROR = 100 # number of errors detected by parser
|
||||
|
||||
def __init__(self, path, table, start, stop, offset=0, device=None):
|
||||
"""
|
||||
Read the given track.
|
||||
@@ -282,6 +294,11 @@ class ReadTrackTask(task.Task):
|
||||
for line in lines:
|
||||
self._parser.parse(line)
|
||||
|
||||
# fail if too many errors
|
||||
if self._parser.errors > self._MAXERROR:
|
||||
self.debug('%d errors, terminating', self._parser.errors)
|
||||
self._popen.terminate()
|
||||
|
||||
num = float(self._parser.wrote) - self._start
|
||||
den = float(self._stop) - self._start
|
||||
progress = num / den
|
||||
|
||||
2501
morituri/test/cdparanoia.progress.error
Normal file
2501
morituri/test/cdparanoia.progress.error
Normal file
File diff suppressed because it is too large
Load Diff
@@ -22,3 +22,21 @@ class ParseTestCase(unittest.TestCase):
|
||||
|
||||
q = '%.01f %%' % (self._parser.getTrackQuality() * 100.0, )
|
||||
self.assertEquals(q, '99.7 %')
|
||||
|
||||
class ErrorTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# report from a rip with offset -1164 causing scsi errors
|
||||
path = os.path.join(os.path.dirname(__file__),
|
||||
'cdparanoia.progress.error')
|
||||
self._parser = cdparanoia.ProgressParser(start=0, stop=10800)
|
||||
|
||||
self._handle = open(path)
|
||||
|
||||
def testParse(self):
|
||||
for line in self._handle.readlines():
|
||||
self._parser.parse(line)
|
||||
|
||||
q = '%.01f %%' % (self._parser.getTrackQuality() * 100.0, )
|
||||
self.assertEquals(q, '99.7 %')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user