[Tutor] "standard output: Broken pipe"

Martin Walsh mwalsh at groktech.org
Tue Oct 23 07:46:17 CEST 2007


Eric Brunson wrote:
> Martin Walsh wrote:
>> Michael Langford wrote:
>> I don't think this is quite right, but please correct me if I'm
>> misinformed, or just plain wrong. :)
>>
>> Using "signal.signal(signal.SIGPIPE, signal.SIG_IGN)" (kernel 2.6.20,
>> bash 3.2, python2.5) 
> 
> I just noticed something, Martin.  subprocess.call() on my machine is
> calling the shell as /bin/sh, not /bin/bash.  This changes the behavior
> of bash, possibly causing it to print the message.  (Anyone else think
> that subprocess should honor the SHELL environment variable?)

Yeah, I thought that was strange too, and I completely agree that the
SHELL env var would seem the obvious choice -- or perhaps, a mechanism
to change the shell command. Now that you mention the behavior of
/bin/bash when called as /bin/sh, I guess it could have something to do
with posix compliance, but I don't really understand the implications.

Maybe a quick modification of the subprocess source will shed some
light; setting it to /bin/bash, instead of /bin/sh (or '/bin/bash --posix'):

"""
def _execute_child( ... ):
<snip>
    if shell:
        args = ["/bin/bash", "-c"] + args
<snip>
"""

Unfortunately, no change in the odd SIGPIPE behavior.

Another factoid -- Ubuntu /bin/sh is a symlink to dash. After your
advice to pay closer attention to the shell sub-process, I thought dash
might be the culprit. But alas, it produced the same behavior. And, of
course, changing the symlink to point to bash didn't make a difference
either.

> 
> I can't get any invocation of the commands to generate the error
> message, only when it's called from python does the ouput get
> generated.  Quite interesting, I'd love to know the explanation for that.

I'm seeing the same thing, error message from python and not from shell
or shell scripts. I am still leaning toward signal inheritance as a
likely contributor, which I think would also indicate that the
subprocess module is rolling up an exception and not passing it along.
As I mentioned it's almost all gut-reaction at this point, so far I
haven't found any definitive proof to substantiate. Slow going for me
I'm afraid, to many tangential paths to follow to fill gaps in my
understanding. But it sure is fun.

Again, thanks for you insight Eric!

Marty

> 
> Still poking at it, though.
> 
>> still produces a broken pipe with the following code:
>>
>> import signal
>> import subprocess as sp
>> signal.signal(signal.SIGPIPE, signal.SIG_IGN)
>> sp.call("yes 'Spam' | head -n 10", shell=True)
>>
>> My understanding is that python is *already* overriding with a SIG_IGN
>> for SIGPIPE, and child processes inherit, which explains the difference
>> in behavior when running the command from a shell terminal (on my system
>> at least) vs. a python subprocess object. This is referenced in the
>> signal module docs (http://docs.python.org/lib/module-signal.html), and
>> appears to be confirmed in the python2.5 source (pythonrun.c).
>>
>> Also, while it is unclear in the signal module docs (to me at least), my
>> take on the use of SIG_DFL is to revert (if necessary) to the *system*
>> default action for a signal, not the python default (which is SIG_IGN).
>> Again, this is my interpretation based on a very minimal understanding
>> -- please correct me if I'm wrong.
>>
>>  
>>> The reason you don't see the error on the shell is that the bash shell
>>> does not print notifications of SIGPIPE when running interactively. If
>>> you instead copied your snippit of scripting into a shell script then
>>> called that with "bash foo.sh", you'd see the exact same broken pipe.
>>>     
>>
>> Ok, this isn't true on my system either -- I don't get a broken pipe
>> from a bash script. So, perhaps this is due to the differences in our
>> kernel or bash versions. The version of bash on my system (3.2) has a
>> DONT_REPORT_SIGPIPE define that is honored in both interactive and
>> non-interactive shells. Presumably, this is how the ubuntu binary was
>> compiled.
>>
>>  
>>> Here is what all the signals available do:
>>> http://www.delorie.com/gnu/docs/glibc/libc_471.html
>>>
>>>     
>>
>> Excellent link, thanks! IMO, the signal manpage ('man signal') is also a
>> good resource. On my system, it contains a table of default actions.
>> Here's what it has to say about SIGPIPE:
>>
>> """
>> Signal     Value     Action   Comment
>> -------------------------------------
>> SIGPIPE      13       Term    Broken pipe: write to pipe with no readers
>> """
>>
>> and, the 'Term' action is defined as follows:
>>
>> """
>> Term   Default action is to terminate the process.
>> """
>>
>> Thanks!
>> Marty
>> _______________________________________________
>> Tutor maillist  -  Tutor at python.org
>> http://mail.python.org/mailman/listinfo/tutor
>>   



More information about the Tutor mailing list