G
gb345
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
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