Bug 1473411 - gdb leaks ignored SIGPIPE to child process
gdb leaks ignored SIGPIPE to child process
Status: VERIFIED
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: gdb (Show other bugs)
7.4
Unspecified Unspecified
unspecified Severity unspecified
: rc
: ---
Assigned To: Jan Kratochvil
Michal Kolar
Vladimír Slávik
:
Depends On:
Blocks: 1471969
  Show dependency treegraph
 
Reported: 2017-07-20 14:11 EDT by Eric Blake
Modified: 2017-11-28 09:52 EST (History)
8 users (show)

See Also:
Fixed In Version: gdb-7.6.1-107.el7
Doc Type: No Doc Update
Doc Text:
undefined
Story Points: ---
Clone Of:
Environment:
Last Closed:
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)


External Trackers
Tracker ID Priority Status Summary Last Updated
Sourceware 18653 None None None 2017-07-20 14:54 EDT

  None (edit)
Description Eric Blake 2017-07-20 14:11:52 EDT
Description of problem:
While trying to validate another bug (1468107) regarding whether a process was properly calling signal(SIGPIPE,SIG_IGN), I ran into a weird issue.  I was running the program under test inside gdb (in order to use a breakpoint at an opportune moment to make it easy to trigger SIGPIPE), and was able to get gdb to admit that SIGPIPE was indeed encountered on both my machine and the QE machine. But on my machine, the process died from SIGPIPE, while on the QE machine, the process ignored SIGPIPE, got EPIPE as its read() result, and exited normally.

I finally traced the difference: the QE machine was using an older version of gdb; and apparently, the older version leaks an ignored SIGPIPE to child processes, even when gdb itself was started with SIGPIPE at default status.

Version-Release number of selected component (if applicable):
qemu-img-1.5.3-140.el7.x86_64

How reproducible:
100%

Steps to Reproduce:
1. First, prove that starting child processes indeed defaults to SIGPIPE at default status:
$ sleep 30&
$ grep SigIgn /proc/$!/status
$ kill %1

2. Next, note that gdb itself requests SIGPIPE to be ignored, but the real test is learning whether SIGPIPE is reverted back to default for the child process:
$ gdb --args sleep 30
(gdb) ! grep SigIgn /proc/self/status
(gdb) b main
(gdb) r
(gdb) info thread
(gdb) ! grep SigIgn /proc/XXX/status  # Fill in XXX based on the info thread results

Actual results:
1. For both machines I tested, I get:
$ sleep 30&
[1] 26872
$ grep SigIgn /proc/$!/status
SigIgn:	0000000000000000
$ kill %1
[1]+  Terminated              sleep 30

So I'm in an environment where children start life with SIGPIPE set to SIG_DFL.

2. On the QE machine, I saw:
$ gdb --args sleep 30
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
...
(gdb) ! grep SigIgn /proc/self/status
SigIgn:	0000000001001000
(gdb) b main
Breakpoint 1 at 0x401510
(gdb) r
Starting program: /usr/bin/sleep 30

Breakpoint 1, 0x0000000000401510 in main ()
(gdb) info thread
  Id   Target Id         Frame 
* 1    process 4885 "sleep" 0x0000000000401510 in main ()
(gdb) ! grep SigIgn /proc/4885/status
SigIgn:	0000000001001000
(gdb) 

Ouch - the child process is starting with SigIgn equal to gdb's environment.

Expected results:
On my working machine, I see:

GNU gdb (GDB) Fedora 8.0-13.fc26
...
(gdb) info thread
  Id   Target Id         Frame 
* 1    process 26798 "sleep" 0x0000555555555590 in main ()
(gdb) ! grep SigIgn /proc/26798/status
SigIgn:	0000000000000000


Additional info:
I didn't see anything in gdb 8's /usr/share/doc/gdb/NEWS that mentions that this was an intentional bug fix, but obviously newer gdb is being smarter about restoring the signals that it hands to the child process.  As it cost me some debug time to figure out why QE couldn't reproduce my test, it would be good to backport the fix to RHEL gdb.
Comment 2 Eric Blake 2017-07-20 14:22:31 EDT
The all-zeros SigIgn is a bit weak. You really want to make sure that if gdb starts with something ignored, then the child process ALSO gets started with that same signal ignored.  With working gdb, here's a slightly stronger test:

$ ( trap - BUS; sleep 30& grep SigIgn /proc/$!/status )
SigIgn:	0000000000000006
$ ( trap '' BUS; sleep 30& grep SigIgn /proc/$!/status )
SigIgn:	0000000000000046

Proof that we can control whether 0x40 is ignored during sleep using just the shell (the shell also ignores SIGINT and SIGQUIT during background tasks; that's life, hence why I used SIGBUS to show what I'm actually toggling)

$ ( trap '' BUS; gdb --args sleep 30 )
GNU gdb (GDB) Fedora 8.0-13.fc26
...
(gdb) ! grep SigIgn /proc/self/status
SigIgn:	0000000001001040

# So gdb started with SIGBUS ignored, and additionally ignores SIGPIPE itself...

(gdb) b main
Breakpoint 1 at 0x1590
(gdb) r
Starting program: /usr/bin/sleep 30

Breakpoint 1, 0x0000555555555590 in main ()
(gdb) info thread
  Id   Target Id         Frame 
* 1    process 27153 "sleep" 0x0000555555555590 in main ()
(gdb) ! grep SigIgn /proc/27153/status
SigIgn:	0000000000000040

# ...but the child process sees JUST SIGBUS ignored (ie. the exact environment that we started gdb with, prior to gdb fudging things around)
Comment 4 Pedro Alves 2017-07-21 06:06:57 EDT
> I didn't see anything in gdb 8's /usr/share/doc/gdb/NEWS that mentions that 
> this was an intentional bug fix, but obviously newer gdb is being smarter 
> about restoring the signals that it hands to the child process.

Intentional:
 https://sourceware.org/ml/gdb-patches/2016-08/msg00086.html
Comment 5 Pedro Alves 2017-07-21 06:22:13 EDT
> (gdb) ! grep SigIgn /proc/self/status
> SigIgn:	0000000001001040
> 
> # So gdb started with SIGBUS ignored, and additionally ignores SIGPIPE itself...

GDB should probably be transparent here (!/shell command) too, I guess.
But that'd be a separate bug.
Comment 6 Jan Kratochvil 2017-10-18 15:44:55 EDT
The fix is only a backport of:
  http://sourceware.org/bugzilla/show_bug.cgi?id=18653

It does not deal with Comment 5 issue.
Comment 8 Michal Kolar 2017-11-03 02:54:57 EDT
Seems not resolved. Problem described by reporter is still present in gdb-7.6.1-104.el7.
Spawned process still inherit mask of ignored signals from gdb.

Please review. Thanks.
Comment 9 Jan Kratochvil 2017-11-03 15:09:33 EDT
Sorry, a backport mistake.  Unfortunately it did compile fine and I did not verify it myself.
Comment 11 Michal Kolar 2017-11-23 08:49:13 EST
Reproduced against gdb-7.6.1-100.el7 and verified against gdb-7.6.1-107.el7.

Note You need to log in before you can comment on or make changes to this bug.