Need help w 'Broken pipe' handling
gb345
gb345 at invalid.com
Wed Feb 3 16:51:44 EST 2010
Hi! I'm having a hard time figuring out how to handle a Unix
SIGPIPE exception cleanly. The following short script illustrates
the problem:
------------------------------------------------------------------
#!/usr/bin/python
# sigpipebug.py
import sys
import random
from signal import signal, SIGPIPE, SIGINT
def handle_sigpipe(signo, frame):
print >> sys.stderr, "caught SIGPIPE (%d)" % signo
sys.exit(0)
def handle_sigint(signo, frame):
print >> sys.stderr, "caught SIGINT (%d)" % signo
sys.exit(1)
def my_excepthook(exc_type, exc_obj, exc_tb):
print >> sys.stderr, "excepthook called"
sys.exit(0)
signal(SIGPIPE, handle_sigpipe)
signal(SIGINT, handle_sigint)
# sys.excepthook = my_excepthook
while True:
try:
print random.random()
except IOError as (_, error):
if error == 'Broken pipe':
print >> sys.stderr, 'EXCEPTION: %s' % error
sys.exit(0)
raise
------------------------------------------------------------------
The problem shows up only occasionally; the following bash one-liner
helps to see the problem (terminate with Ctrl-C):
while [ 1 ]; do (./sigpipebug.py||break) | head -1; done
(The pipe through head should cause the script to receive a PIPE
signal.)
The typical output from the above one-liner will start out as
something like this:
0.666233280308
caught SIGPIPE (13)
0.554289690682
caught SIGPIPE (13)
0.438033929588
caught SIGPIPE (13)
0.969307976257
caught SIGPIPE (13)
close failed in file object destructor:
Error in sys.excepthook:
Original exception was:
0.916260186232
caught SIGPIPE (13)
0.798590903019
caught SIGPIPE (13)
0.737496617527
...though the length of the output preceding "close failed..." is
highly variable.
My problem is that I can't figure out how to get rid of this unwanted
extra output:
close failed in file object destructor:
Error in sys.excepthook:
Original exception was:
I figure that the way the script is handling the SIGPIPE is somehow
incorrect, but I don't see what is it that I'm doing wrong (BTW,
I'm a Python noob). Is there some cleanup method I should invoke
in the sigpipe handler before executing sys.exit(0)? (BTW, I'm
using sys.exit in this script instead of plain exit to avoid a
strange error of the form "NameError: global name 'exit' is not
defined".)
The same thing happens when I redefine sys.excepthook (by uncommenting
the commented-out line).
Also, is there a way to define the SIGPIPE handler to obviate the
need to trap the IOError exception? (Without this try block, I
get a traceback when the script receives the PIPE signal. This
traceback is also unwanted output.)
Any suggestions or comments would be appreciated!
Gabe
More information about the Python-list
mailing list