[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
|
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 he 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 | 25 +++++++++++++++++++++++++
gdb/serial.c | 4 ++++
gdb/serial.h | 4 ++++
3 files changed, 33 insertions(+)
Comments
>>>>> "Alexandra" == Alexandra Hájková <ahajkova@redhat.com> writes:
Alexandra> Duplicate the numbers of STDOUT/STDIN/STDERR file descriptors
Alexandra> GDB is connected to. Preserved numbers of the file descriptors
Alexandra> could be then sent to the GDBserver. If GDBserver is run locally
Alexandra> and will accept he numbers of the file descriptors, it can start
Alexandra> the inferior connected to the same STDIN/OUT/ERR, GDB is connected to.
Thanks for the patch.
Alexandra> + /* Preserve STDIN/STDOUT/STDERR so they won't be closed on
Alexandra> + exec later, after we fork. */
Alexandra> + int saved_stdin = dup (STDIN_FILENO);
Alexandra> + int saved_stdout = dup (STDOUT_FILENO);
Alexandra> + int saved_stderr = dup (STDERR_FILENO);
I wonder what should happen if any of these fail.
Alexandra> @@ -128,6 +144,10 @@ pipe_open (struct serial *scb, const char *name)
Alexandra> close (err_pdes[1]);
Alexandra> }
Alexandra> + mark_fd_no_cloexec (saved_stdout);
Alexandra> + mark_fd_no_cloexec (saved_stdin);
Alexandra> + mark_fd_no_cloexec (saved_stderr);
Alexandra> +
This happens in the child process, but due to vfork, it actually affects
the parent process as well. vfork is weird.
However I think this introduces a funny bug, in that these particular
descriptors are marked as no-cloexec by number. So, while they are
closed again in the parent:
Alexandra> + close (saved_stdout);
Alexandra> + close (saved_stdin);
Alexandra> + close (saved_stderr);
... their numbers are preserved for not-closing, and so it's possible
they could be reused and inherited by accident by some future
subprocess.
Probably these closes in the parent should be paired with calls to
unmark_fd_no_cloexec.
I'd suggest hoisting the calls to mark_fd_no_cloexec near the dup()s,
too, just to make it more clear.
Tom
@@ -77,6 +77,16 @@ pipe_open (struct serial *scb, const char *name)
return -1;
}
+ /* 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);
+
+ 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''
@@ -90,6 +100,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;
return -1;
}
@@ -128,6 +144,10 @@ pipe_open (struct serial *scb, const char *name)
close (err_pdes[1]);
}
+ mark_fd_no_cloexec (saved_stdout);
+ mark_fd_no_cloexec (saved_stdin);
+ mark_fd_no_cloexec (saved_stderr);
+
close_most_fds ();
const char *shellfile = get_shell ();
@@ -139,6 +159,11 @@ pipe_open (struct serial *scb, const char *name)
close (pdes[1]);
if (err_pdes[1] != -1)
close (err_pdes[1]);
+
+ close (saved_stdout);
+ close (saved_stdin);
+ close (saved_stderr);
+
/* :end chunk */
state = XNEW (struct pipe_state);
state->pid = pid;
@@ -182,6 +182,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