This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: RFC: close-on-exec internal file descriptors
- From: Tom Tromey <tromey at redhat dot com>
- To: Joel Brobecker <brobecker at adacore dot com>
- Cc: gdb-patches at sourceware dot org
- Date: Mon, 06 May 2013 12:53:54 -0600
- Subject: Re: RFC: close-on-exec internal file descriptors
- References: <874njjs1aa dot fsf at fleche dot redhat dot com> <m2vcbzui0o dot fsf at igel dot home> <87fw32p00e dot fsf at fleche dot redhat dot com> <874niy6y35 dot fsf at fleche dot redhat dot com> <87d2tmsey0 dot fsf at fleche dot redhat dot com> <20130501144722 dot GA10034 at adacore dot com>
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> Unfortunately, this is causing problems on Darwin and HP/UX,
Joel> because both platforms use pipes to synchronize parent and
Joel> child during the fork/exec. See for instance darwin-nat.c:
Sorry Joel.
I did not even consider this possibility.
Joel> I don't think there is a way of opening a FD with the intention
Joel> of protecting them from the close-at-exec, is there? So, the solution
Joel> would seem to add an interface to setup the protection, as well
Joel> as a function to remove that protection (necessary when we close
Joel> the fd).
Joel> What do you think?
Could you try the appended? I can't even build parts of it, so...
I think it is pretty ugly, since it is a layer on top of the
kernel-level cloexec flags. However, that is another discussion, from
the earlier reviews.
Tom
diff --git a/gdb/common/filestuff.c b/gdb/common/filestuff.c
index 68f66ca..e7af3a5 100644
--- a/gdb/common/filestuff.c
+++ b/gdb/common/filestuff.c
@@ -177,6 +177,33 @@ notice_open_fds (void)
fdwalk (do_mark_open_fd, NULL);
}
+/* See filestuff.h. */
+
+void
+mark_fd_no_cloexec (int fd)
+{
+ do_mark_open_fd (NULL, fd);
+}
+
+/* See filestuff.h. */
+
+void
+unmark_fd_no_cloexec (int fd)
+{
+ int i, val;
+
+ for (i = 0; VEC_iterate (int, open_fds, i, val); ++i)
+ {
+ if (fd == val)
+ {
+ VEC_unordered_remove (int, open_fds, i);
+ return;
+ }
+ }
+
+ gdb_assert_not_reached (_("fd not found in open_fds"));
+}
+
/* Helper function for close_most_fds that closes the file descriptor
if appropriate. */
diff --git a/gdb/common/filestuff.h b/gdb/common/filestuff.h
index 0db33f0..b162a0c 100644
--- a/gdb/common/filestuff.h
+++ b/gdb/common/filestuff.h
@@ -24,6 +24,16 @@
extern void notice_open_fds (void);
+/* Mark a file descriptor as inheritable across an exec. */
+
+extern void mark_fd_no_cloexec (int fd);
+
+/* Mark a file descriptor as no longer being inheritable across an
+ exec. This is only meaningful when FD was previously passed to
+ mark_fd_no_cloexec. */
+
+extern void unmark_fd_no_cloexec (int fd);
+
/* Close all open file descriptors other than those marked by
'notice_open_fds', and stdin, stdout, and stderr. Errors that
occur while closing are ignored. */
diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c
index acdbf36..b7a8b35 100644
--- a/gdb/darwin-nat.c
+++ b/gdb/darwin-nat.c
@@ -1516,6 +1516,9 @@ darwin_pre_ptrace (void)
ptrace_fds[1] = -1;
error (_("unable to create a pipe: %s"), safe_strerror (errno));
}
+
+ mark_fd_no_cloexec (ptrace_fds[0]);
+ mark_fd_no_cloexec (ptrace_fds[1]);
}
static void
@@ -1533,6 +1536,9 @@ darwin_ptrace_him (int pid)
close (ptrace_fds[0]);
close (ptrace_fds[1]);
+ unmark_fd_no_cloexec (ptrace_fds[0]);
+ unmark_fd_no_cloexec (ptrace_fds[1]);
+
darwin_init_thread_list (inf);
startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
diff --git a/gdb/inf-ttrace.c b/gdb/inf-ttrace.c
index 642e520..f39df49 100644
--- a/gdb/inf-ttrace.c
+++ b/gdb/inf-ttrace.c
@@ -558,6 +558,11 @@ do_cleanup_pfds (void *dummy)
close (inf_ttrace_pfd1[1]);
close (inf_ttrace_pfd2[0]);
close (inf_ttrace_pfd2[1]);
+
+ unmark_fd_no_cloexec (inf_ttrace_pfd1[0]);
+ unmark_fd_no_cloexec (inf_ttrace_pfd1[1]);
+ unmark_fd_no_cloexec (inf_ttrace_pfd2[0]);
+ unmark_fd_no_cloexec (inf_ttrace_pfd2[1]);
}
static void
@@ -572,6 +577,11 @@ inf_ttrace_prepare (void)
close (inf_ttrace_pfd2[0]);
perror_with_name (("pipe"));
}
+
+ mark_fd_no_cloexec (inf_ttrace_pfd1[0]);
+ mark_fd_no_cloexec (inf_ttrace_pfd1[1]);
+ mark_fd_no_cloexec (inf_ttrace_pfd2[0]);
+ mark_fd_no_cloexec (inf_ttrace_pfd2[1]);
}
/* Prepare to be traced. */