diff options
author | Pedro Alves <palves@redhat.com> | 2017-10-19 16:00:21 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2017-10-19 16:00:21 +0100 |
commit | a75868f50ba72e9aa906702ae038fa29feda7743 (patch) | |
tree | 456ad7756d5a0b466165ec440956f8516e777345 /gdb/ser-base.c | |
parent | 2edf834e298b15c882678db22e86745f701807fa (diff) | |
download | gdb-a75868f50ba72e9aa906702ae038fa29feda7743.zip gdb-a75868f50ba72e9aa906702ae038fa29feda7743.tar.gz gdb-a75868f50ba72e9aa906702ae038fa29feda7743.tar.bz2 |
Fix inferior deadlock with "target remote | CMD"
Comparing test results between
--target_board=native-gdbserver
--target_board=native-stdio-gdbserver
I noticed that gdb.base/bigcore.exp is failing with native-stdio-gdbserver:
Running src/gdb/testsuite/gdb.base/bigcore.exp ...
FAIL: gdb.base/bigcore.exp: continue (timeout)
...
The problem is that:
1. When debugging with "target remote | CMD", the inferior's
stdout/stderr streams are connected to a pipe.
2. The bigcore.c program prints a lot to the screen before it
reaches the breakpoint location that the "continue" shown above
wants to reach.
3. GDB is not flushing the inferior's output pipe while the inferior
is running.
4. The pipe becomes full.
5. The inferior thus deadlocks.
The bug is #3 above, which is what this commit fixes. A new test is
added, that specifically exercises this scenario. The test fails
before the fix, and passes after, and gdb.base/bigcore.exp also starts
passing.
gdb/ChangeLog:
2017-10-19 Pedro Alves <palves@redhat.com>
* ser-base.c (ser_base_read_error_fd): Delete the file handler if
async.
(handle_error_fd): New function.
(ser_base_async): Add/delete an event loop file handler for
error_fd.
gdb/testsuite/ChangeLog:
2017-10-19 Pedro Alves <palves@redhat.com>
* gdb.base/long-inferior-output.c: New file.
* gdb.base/long-inferior-output.exp: New file.
Diffstat (limited to 'gdb/ser-base.c')
-rw-r--r-- | gdb/ser-base.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/gdb/ser-base.c b/gdb/ser-base.c index 790cb1b..2bfe82b 100644 --- a/gdb/ser-base.c +++ b/gdb/ser-base.c @@ -288,6 +288,8 @@ ser_base_read_error_fd (struct serial *scb, int close_fd) if (s == 0 && close_fd) { /* End of file. */ + if (serial_is_async_p (scb)) + delete_file_handler (scb->error_fd); close (scb->error_fd); scb->error_fd = -1; break; @@ -313,6 +315,17 @@ ser_base_read_error_fd (struct serial *scb, int close_fd) } } +/* Event-loop callback for a serial's error_fd. Flushes any error + output we might have. */ + +static void +handle_error_fd (int error, gdb_client_data client_data) +{ + serial *scb = (serial *) client_data; + + ser_base_read_error_fd (scb, 0); +} + /* Read a character with user-specified timeout. TIMEOUT is number of seconds to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns char if successful. Returns SERIAL_TIMEOUT if @@ -589,6 +602,9 @@ ser_base_async (struct serial *scb, fprintf_unfiltered (gdb_stdlog, "[fd%d->asynchronous]\n", scb->fd); reschedule (scb); + + if (scb->error_fd != -1) + add_file_handler (scb->error_fd, handle_error_fd, scb); } else { @@ -607,5 +623,8 @@ ser_base_async (struct serial *scb, delete_timer (scb->async_state); break; } + + if (scb->error_fd != -1) + delete_file_handler (scb->error_fd); } } |