Subject: 23.2; Emacs's SIGPIPE ignore passed to child processes

From: Juergen Nickelsen <[email-masked]>
Date: Thu, 30 Jan 2014 17:44:35 +0100

The problem:

Emacs sets SIGPIPE handling to SIG_IGN, probably for good reasons. But
this setting is also passed on to subprocesses, which can make some
programs misbehave.

I think it would be better to reset the SIGPIPE handling in the
subprocess before calling the shell (or whatever).

To reproduce:

In a directory that contains the root of a git repository with a largish
file (130295 bytes in this case) that is also checked in into the
repository, I start "emacs -Q".

In Emacs, I run the executable Perl script "./broken.pl" (contents
below) as a shell command using M-! (shell-command):

--------broken.pl----------------------------------------------------
#!/usr/bin/perl
# demonstrate Emacs's SIGPIPE issue

use Git;

print("SIGPIPE: $SIG{PIPE}\n");
# $SIG{PIPE} = 'DEFAULT';
# print("SIGPIPE: $SIG{PIPE}\n");
my $content = Git::command_oneline(qw(show HEAD:largefile));
print("$content\n");
---------------------------------------------------------------------

The output is, as can also be seen below:

SIGPIPE: IGNORE
show HEAD:largefile: command returned error: 255

This does not happen with really small files instead of largefile,
e.g. 1.5 KB. It also does not happen if the line with "$SIG{PIPE} =
'DEFAULT';" is reset, so the SIGPIPE is no longer ignored.

Colleagues and I have pondered this for a while, and after examining
some code and tracing the syscalls involved we have come up with the
following explanation:

The Perl Git library's function "command_oneline()" closes the pipe to
its git subprocess after reading one line. If the file is short, it can
be written into the pipe without fault, and the git process exit()s
fast. If the file is large enough, the git subprocess would normally
block on write() when the pipe is full and would finally be terminated
by a SIGPIPE when the pipe is closed by the reader (the Perl process).

But if SIGPIPE is set to SIG_IGN, the write() fails, and git exits with
a non-zero exit status. This makes the Perl wrapper assume something
went wrong (which it technically did), and it throws an exception.

The issue can be worked around by (setq shell-command-switch "-ic") so
the shell resets the signal handling, but that makes the shell complain
about not being able to access its terminal's process group (small
surprise!).

Best regards,
Juergen.

***************
In GNU Emacs 23.2.1 (x86_64-pc-linux-gnu, GTK+ Version 2.20.1)
 of 2012-08-25 on trouble, modified by Debian
Windowing system distributor `The X.Org Foundation', version 11.0.10707000
configured using `configure  '--build' 'x86_64-linux-gnu' '--build' 'x86_64-linux-gnu' '--prefix=/usr' '--sharedstatedir=/var/lib' '--libexecdir=/usr/lib' '--localstatedir=/var/lib' '--infodir=/usr/share/info' '--mandir=/usr/share/man' '--with-pop=yes' '--enable-locallisppath=/etc/emacs23:/etc/emacs:/usr/local/share/emacs/23.2/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/23.2/site-lisp:/usr/share/emacs/site-lisp:/usr/share/emacs/23.2/leim' '--with-x=yes' '--with-x-toolkit=gtk' '--with-toolkit-scroll-bars' 'build_alias=x86_64-linux-gnu' 'CFLAGS=-DDEBIAN -g -O2' 'LDFLAGS=-g' 'CPPFLAGS=''

Important settings:
  value of $LC_ALL: nil
  value of $LC_COLLATE: C
  value of $LC_CTYPE: de_DE@euro
  value of $LC_MESSAGES: nil
  value of $LC_MONETARY: nil
  value of $LC_NUMERIC: nil
  value of $LC_TIME: nil
  value of $LANG: C
  value of $XMODIFIERS: nil
  locale-coding-system: iso-latin-9-unix
  default enable-multibyte-characters: t

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t

Recent input:
M-! . / b r o k e n . p l <return> M-x r e p o r t 
<tab> <return>

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
SIGPIPE: IGNORE
show HEAD:largefile: command returned error: 255

Load-path shadows:
/usr/share/emacs/23.2/site-lisp/cmake-data/cmake-mode hides /usr/share/emacs/site-lisp/cmake-mode
/usr/share/emacs/23.2/site-lisp/debian-startup hides /usr/share/emacs/site-lisp/debian-startup
/usr/share/emacs/23.2/site-lisp/dictionaries-common/flyspell hides /usr/share/emacs/23.2/lisp/textmodes/flyspell
/usr/share/emacs/23.2/site-lisp/dictionaries-common/ispell hides /usr/share/emacs/23.2/lisp/textmodes/ispell

Features:
(shadow sort mail-extr message sendmail regexp-opt ecomplete rfc822 mml
easymenu mml-sec password-cache mm-decode mm-bodies mm-encode mailcap
mail-parse rfc2231 rfc2047 rfc2045 qp ietf-drums mailabbrev nnheader
gnus-util netrc time-date mm-util mail-prsvr gmm-utils wid-edit
mailheader canlock sha1 hex-util hashcash mail-utils emacsbug tooltip
ediff-hook vc-hooks lisp-float-type mwheel x-win x-dnd font-setting
tool-bar dnd fontset image fringe lisp-mode register page menu-bar
rfn-eshadow timer select scroll-bar mldrag mouse jit-lock font-lock
syntax facemenu font-core frame cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
case-table epa-hook jka-cmpr-hook help simple abbrev loaddefs button
minibuffer faces cus-face files text-properties overlay md5 base64
format env code-pages mule custom widget hashtable-print-readable
backquote make-network-process dbusbind system-font-setting
font-render-setting gtk x-toolkit x multi-tty emacs)

-- 
<[email-masked]> Tel +49.30.838-50740 Fax -450740
Zentraleinrichtung fuer Datenverarbeitung, Central Systems (Unix)
Freie Universitaet Berlin, Fabeckstrasse 32, 14195 Berlin, DE