Bug 26056

Summary: SIGSEGV in tui_async_resize_screen -> rl_resize_terminal on SIGWINCH with non-tty stdin/stdout
Product: gdb Reporter: Michael Pratt <mpratt>
Component: gdbAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: anudeephomes247, ashish.lumar2902, lsix, mark, tromey, tulzakasi
Priority: P2    
Version: HEAD   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed: 2020-08-09 00:00:00

Description Michael Pratt 2020-05-27 21:11:10 UTC
When GDB is run with stdin == /dev/null and stdout/stderr == pipe [1] and subsequently sent sent a SIGWINCH signal, it will crash with a SIGSEGV/SIGABRT (depending on version).

At HEAD (specifically dcb5d41befce097d48875e744f57fe3209c61aab):

$ gdb/gdb -nx -batch -ex 'run' --args sleep 60 </dev/null 2>&1 | cat                                                                          
Python Exception <type 'exceptions.ImportError'> No module named gdb:  
gdb/gdb: warning:                                                                                                                            
Could not load the Python gdb module from `/usr/local/share/gdb/python'.
Limited Python support is available from the _gdb module.
Suggest passing --data-directory=/path/to/gdb/data-directory.
zsh: abort      gdb/gdb -nx -batch -ex 'run' --args sleep 60 < /dev/null 2>&1 | 
zsh: done       cat 

While running:
$ pkill -WINCH gdb

The crashing stack is:

(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007f3e39c4b55b in __GI_abort () at abort.c:79
#2  0x000055d51f121260 in handle_sigsegv (sig=11) at event-top.c:885
#3  <signal handler called>
#4  __GI___fileno (fp=0x0) at fileno.c:35
#5  0x000055d51f4964a0 in rl_resize_terminal () at terminal.c:368
#6  0x000055d51f44117b in tui_async_resize_screen (arg=<optimized out>) at tui/tui-win.c:541
#7  0x000055d51f171a02 in invoke_async_signal_handlers () at async-event.c:206
#8  0x000055d51f5581ae in gdb_do_one_event () at event-loop.cc:172
#9  0x000055d51f41ef9c in wait_sync_command_done () at top.c:526
#10 0x000055d51f41f435 in maybe_wait_sync_command_done (was_sync=0) at top.c:543
#11 execute_command (p=<optimized out>, p@entry=<error reading variable: value has been optimized out>, from_tty=<error reading variable: value has been optimized out>) at top.c:657
#12 0x000055d51f3042f0 in catch_command_errors (command=<optimized out>, arg=<optimized out>, from_tty=<optimized out>) at main.c:457
#13 0x000055d51f3058d9 in captured_main_1 (context=<optimized out>) at main.c:1219
#14 0x000055d51f30615b in captured_main (data=<optimized out>) at main.c:1269
#15 gdb_main (args=<optimized out>) at main.c:1269
#16 0x000055d51f13750c in main (argc=<optimized out>, argv=<optimized out>) at gdb.c:32

With my system GDB (Debian 8.3.1-1):

$ gdb -nx -batch -ex 'run' --args sleep 60 </dev/null 2>&1 | cat    
zsh: segmentation fault  gdb -nx -batch -ex 'run' --args sleep 60 < /dev/null 2>&1 | 
zsh: done                cat

The crashing stack is the same, there is just no SIGSEGV handler that translates the SIGSEGV to SIGABRT.

I've seen this crash on HEAD, 8.3, 8.2, 8.1, and 7.12.

This bug was discovered when investigating flaky GDB integration tests in the Go project: https://github.com/golang/go/issues/39021. Those tests use the Go os/exec.Command.CombinedOutput() stdlib function (same Go code: https://github.com/golang/go/issues/39021#issuecomment-634919443). This function runs the subprocess with stdin set to /dev/null and stdout and stderr set to a pipe.

As I understand it, the immediate problem is that rl_resize_terminal is expected to crash when rl_initialize has not been called. In some non-interactive cases (not sure of the exact behavior), GDB doesn't call rl_initialize because it is "unnecessary". Yet, it still installs the tui_async_resize_screen SIGWINCH handler, which unconditionally calls rl_resize_terminal.

In addition to a fix, I've been looking for a good workaround to convince GDB not to crash.

[1] I believe a more common set of non-tty I/O will trigger this bug, but these are the specific inputs I've used to reproduce the issue.
Comment 1 Tom Tromey 2020-08-09 18:51:51 UTC
FWIW this seems to work ok with git gdb.
There have been many TUI changes since 8.3, including in
the readline initialization area.

Could you try git gdb and see if it works?
Comment 2 Michael Pratt 2020-08-10 14:58:40 UTC
I'm still seeing the same behavior at 3eb651743e06fb360687a26be87bc6b710fc7066 ("Implement missing powerpc mtspr and mfspr extended insns").

$ gdb/gdb -nx -batch -ex 'run' --args sleep 60 </dev/null 2>&1 | cat
Python Exception <type 'exceptions.ImportError'> No module named gdb:
gdb/gdb: warning:
Could not load the Python gdb module from `/usr/local/share/gdb/python'.
Limited Python support is available from the _gdb module.
Suggest passing --data-directory=/path/to/gdb/data-directory. 
zsh: abort      gdb/gdb -nx -batch -ex 'run' --args sleep 60 < /dev/null 2>&1 |
zsh: done       cat   

$ pkill -WINCH gdb

Same crash location:

(top-gdb) bt
#0  __GI___fileno (fp=0x0) at fileno.c:35
#1  0x000055d06e689d40 in rl_resize_terminal () at terminal.c:368
#2  0x000055d06e634c0b in tui_async_resize_screen (arg=<optimized out>) at tui/tui-win.c:541
#3  0x000055d06e358ee2 in invoke_async_signal_handlers () at async-event.c:206
#4  0x000055d06e751e4e in gdb_do_one_event () at event-loop.cc:172
#5  0x000055d06e6126cc in wait_sync_command_done () at top.c:526
#6  0x000055d06e612e32 in maybe_wait_sync_command_done (was_sync=0) at top.c:543
#7  execute_command (p=<optimized out>, p@entry=<error reading variable: value has been optimized out>, from_tty=<error reading variable: value has been optimized out>) at top.c:670
#8  0x000055d06e4f3b50 in catch_command_errors (command=<optimized out>, arg=<optimized out>, from_tty=<optimized out>) at main.c:457
#9  0x000055d06e4f5119 in captured_main_1 (context=<optimized out>) at main.c:1218
#10 0x000055d06e4f59bb in captured_main (data=<optimized out>) at main.c:1268
#11 gdb_main (args=<optimized out>) at main.c:1268
#12 0x000055d06e31dd9c in main (argc=<optimized out>, argv=<optimized out>) at gdb.c:32
Comment 3 anudeep homes247 2021-02-10 10:28:55 UTC Comment hidden (spam)
Comment 4 godrejanandabagalur 2021-05-20 12:15:48 UTC Comment hidden (spam)
Comment 5 Alex Sam 2021-09-08 08:27:46 UTC Comment hidden (spam)
Comment 6 Lancelot SIX 2021-12-17 22:12:23 UTC
Fixed in commit 72994b6028360eccb5d25b39d2e18b386d091426.