[v2,2/6] gdb/ser-pipe.c: Duplicate the file descriptors
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-arm |
success
|
Testing passed
|
Commit Message
Duplicate the numbers of STDOUT/STDIN/STDERR file descriptors
GDB is connected to. Preserved numbers of the file descriptors
could be then sent to the gdbserver. If gdbserver is run locally
and will accept the numbers of the file descriptors, it can start
the inferior connected to the same STDIN/OUT/ERR, GDB is connected to.
---
gdb/ser-pipe.c | 40 ++++++++++++++++++++++++++++++++++++++++
gdb/serial.c | 4 ++++
gdb/serial.h | 4 ++++
3 files changed, 48 insertions(+)
@@ -77,6 +77,32 @@ pipe_open (struct serial *scb, const char *name)
perror_with_name (_("could not open socket pair"), save);
}
+ /* Preserve STDIN/STDOUT/STDERR so they won't be closed on
+ exec later, after we fork. */
+ int saved_stdin = dup (STDIN_FILENO);
+ int saved_stdout = dup (STDOUT_FILENO);
+ int saved_stderr = dup (STDERR_FILENO);
+ if (saved_stdin == -1 || saved_stdout == -1 || saved_stderr == -1)
+ {
+ /* If any FD failed to dup() then we can't used the default-fd mechanism,
+ so close any files that succeeded. */
+ if (saved_stdin == -1)
+ close (saved_stdin);
+ if (saved_stdout == -1)
+ close (saved_stdout);
+ if (saved_stderr == -1)
+ close (saved_stderr);
+ saved_stdin = saved_stdout = saved_stderr = -1;
+ }
+
+ mark_fd_no_cloexec (saved_stdout);
+ mark_fd_no_cloexec (saved_stdin);
+ mark_fd_no_cloexec (saved_stderr);
+
+ scb->fds[0] = saved_stdin;
+ scb->fds[1] = saved_stdout;
+ scb->fds[2] = saved_stderr;
+
/* Create the child process to run the command in. Note that the
apparent call to vfork() below *might* actually be a call to
fork() due to the fact that autoconf will ``#define vfork fork''
@@ -91,6 +117,12 @@ pipe_open (struct serial *scb, const char *name)
close (pdes[1]);
close (err_pdes[0]);
close (err_pdes[1]);
+ close (saved_stdout);
+ close (saved_stdin);
+ close (saved_stderr);
+ scb->fds[0] = -1;
+ scb->fds[1] = -1;
+ scb->fds[2] = -1;
perror_with_name (_("could not vfork"), save);
}
@@ -140,6 +172,14 @@ pipe_open (struct serial *scb, const char *name)
close (pdes[1]);
if (err_pdes[1] != -1)
close (err_pdes[1]);
+
+ unmark_fd_no_cloexec(saved_stdout);
+ unmark_fd_no_cloexec(saved_stdin);
+ unmark_fd_no_cloexec(saved_stderr);
+ close (saved_stdout);
+ close (saved_stdin);
+ close (saved_stderr);
+
/* :end chunk */
state = XNEW (struct pipe_state);
state->pid = pid;
@@ -180,6 +180,10 @@ new_serial (const struct serial_ops *ops)
scb->ops = ops;
+ scb->fds[0] = -1;
+ scb->fds[1] = -1;
+ scb->fds[2] = -1;
+
scb->bufp = scb->buf;
scb->error_fd = -1;
scb->refcnt = 1;
@@ -254,6 +254,10 @@ struct serial
int async_state; /* Async internal state. */
void *async_context; /* Async event thread's context */
serial_event_ftype *async_handler;/* Async event handler */
+
+ /* File descriptors for preserved STDIN/STDOUT/STDERR
+ to be sent to gdbserver when run locally. */
+ int fds[3];
};
struct serial_ops