From: Avery Pennarun Date: Wed, 3 Mar 2010 04:18:49 +0000 (-0500) Subject: log(): handle situations where stderr gets set to nonblocking. X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=046fb8ee84131b5839fbaf4add2498a1236e96c3;p=packages%2Fb%2Fbup.git log(): handle situations where stderr gets set to nonblocking. It's probably ssh doing this, and in obscure situations, it means log() ends up throwing an exception and aborting the program. Fix it so that we handle EAGAIN correctly if we get it when writing to stderr, even though this is only really necessary due to stupidity on (I think/hope) someone else's part. --- diff --git a/lib/bup/helpers.py b/lib/bup/helpers.py index 75cf09c..0aa6945 100644 --- a/lib/bup/helpers.py +++ b/lib/bup/helpers.py @@ -1,8 +1,25 @@ import sys, os, pwd, subprocess, errno, socket, select, mmap, stat, re +# Write (blockingly) to sockets that may or may not be in blocking mode. +# We need this because our stderr is sometimes eaten by subprocesses +# (probably ssh) that sometimes make it nonblocking, if only temporarily, +# leading to race conditions. Ick. We'll do it the hard way. +def _hard_write(fd, buf): + while buf: + (r,w,x) = select.select([], [fd], [], None) + if not w: + raise IOError('select(fd) returned without being writable') + try: + sz = os.write(fd, buf) + except OSError, e: + if e.errno != errno.EAGAIN: + raise + assert(sz >= 0) + buf = buf[sz:] + def log(s): - sys.stderr.write(s) + _hard_write(sys.stderr.fileno(), s) def mkdirp(d):