Odd python proc control / buffering behaviour
Martin Langhoff
martin.langhoff at gmail.com
Fri Aug 1 23:29:49 EDT 2008
something very basic is not working well with Python - reading 1MB
from a process and writing it to a file gets truncated at random
points. Not being a native Python speaker, review and comments
welcome. Hopefully I'm not losing my mind just yet.
Summary:
- The script untars an XO image under fakeroot, saving a 1MB "state"
file from fakeroot.
- Then concatenate all the "state" files from all the builds into a master one.
- The concatenation ends up truncated (due to buffering issues?)
Some interesting aspects
- If I comment out the untarring of the image just before we hit this
code, the bug disappears.
- If we sleep for 1s, the bug disappears!
- output redirection under os.system() also suffers the problem
- os.fdatasync(), proc.wait() don't seem to help
- there is no corruption in the file - just truncated
- the truncation is not at a newline
Code affected:
... just after untarring the image -
# (cat *.state > .tmpstate) && mv .tmpstate rsyncd.all
(tmpfh, tmpfpath) = tempfile.mkstemp()
# Uncomment the line below and the truncation goes away!
# time.sleep(1)
# Using os.system() shows truncation problems
#os.system('find %s -type f -name \'*.state\' -print0 | xargs -0
--no-run-if-empty cat > %s' % (options.statedir, tmpfpath))
#
# The Python way - shows truncation problems
#
pfind = Popen(['find', options.statedir, '-type', 'f',
'-name', '*.state', '-print0'], stdout=PIPE)
pxargs = Popen(['xargs', '-0', '--no-run-if-empty', 'cat'],
stdin=pfind.stdout,stdout=tmpfh)
# wait() or a small loop checking for poll()!=None
# neither helps
pxargs.wait()
# fdatasync() does not make a difference
os.fdatasync(tmpfh)
os.close(tmpfh)
Changing the stdout of pxargs to PIPE and reading it explicitly with a loop like
while True:
buf = pxargs.stdout.read(4096)
if not buf:
if pxargs.poll() == None:
continue
break
os.write(tmpfs,buf)
does not make any difference either.
The truncation is not stable - the file should get 1036681 bytes, and
it gets anywhere from 300KB to 700KB. I suspect that Python is
forgetting to flush the buffers when the process finishes. This is
python 2.5-15.fc7 on the XS image.
Any hints? Ideas?
m
--
martin.langhoff at gmail.com
martin at laptop.org -- School Server Architect
- ask interesting questions
- don't get distracted with shiny stuff - working code first
- http://wiki.laptop.org/go/User:Martinlanghoff
More information about the Devel
mailing list