[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 08/27: Factor start_child out of open_process
From: |
Andy Wingo |
Subject: |
[Guile-commits] 08/27: Factor start_child out of open_process |
Date: |
Mon, 25 Jul 2016 09:53:45 +0000 (UTC) |
wingo pushed a commit to branch master
in repository guile.
commit 10ae9cc60197562c72f3a8311bb64d62778df250
Author: Andy Wingo <address@hidden>
Date: Mon Jul 11 22:46:55 2016 +0200
Factor start_child out of open_process
* libguile/posix.c (start_child): Factor out from open_process. Based
on initial work by Eli Zaretskii.
---
libguile/posix.c | 188 ++++++++++++++++++++++++++++++------------------------
1 file changed, 104 insertions(+), 84 deletions(-)
diff --git a/libguile/posix.c b/libguile/posix.c
index 8aa0f3e..8b3fabc 100644
--- a/libguile/posix.c
+++ b/libguile/posix.c
@@ -1236,10 +1236,96 @@ SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0,
return scm_from_int (pid);
}
#undef FUNC_NAME
+#endif /* HAVE_FORK */
+#ifdef HAVE_FORK
+#define HAVE_START_CHILD 1
/* Since Guile uses threads, we have to be very careful to avoid calling
functions that are not async-signal-safe in the child. That's why
this function is implemented in C. */
+static pid_t
+start_child (const char *exec_file, char **exec_argv,
+ int reading, int c2p[2], int writing, int p2c[2],
+ int in, int out, int err)
+{
+ int pid;
+ int max_fd = 1024;
+
+#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_NOFILE)
+ {
+ struct rlimit lim = { 0, 0 };
+ if (getrlimit (RLIMIT_NOFILE, &lim) == 0)
+ max_fd = lim.rlim_cur;
+ }
+#endif
+
+ pid = fork ();
+
+ if (pid != 0)
+ /* The parent, with either and error (pid == -1), or the PID of the
+ child. Return directly in either case. */
+ return pid;
+
+ /* The child. */
+ if (reading)
+ close (c2p[0]);
+ if (writing)
+ close (p2c[1]);
+
+ /* Close all file descriptors in ports inherited from the parent
+ except for in, out, and err. Heavy-handed, but robust. */
+ while (max_fd--)
+ if (max_fd != in && max_fd != out && max_fd != err)
+ close (max_fd);
+
+ /* Ignore errors on these open() calls. */
+ if (in == -1)
+ in = open ("/dev/null", O_RDONLY);
+ if (out == -1)
+ out = open ("/dev/null", O_WRONLY);
+ if (err == -1)
+ err = open ("/dev/null", O_WRONLY);
+
+ if (in > 0)
+ {
+ if (out == 0)
+ do out = dup (out); while (errno == EINTR);
+ if (err == 0)
+ do err = dup (err); while (errno == EINTR);
+ do dup2 (in, 0); while (errno == EINTR);
+ close (in);
+ }
+ if (out > 1)
+ {
+ if (err == 1)
+ do err = dup (err); while (errno == EINTR);
+ do dup2 (out, 1); while (errno == EINTR);
+ close (out);
+ }
+ if (err > 2)
+ {
+ do dup2 (err, 2); while (errno == EINTR);
+ close (err);
+ }
+
+ execvp (exec_file, exec_argv);
+
+ /* The exec failed! There is nothing sensible to do. */
+ if (err > 0)
+ {
+ char *msg = strerror (errno);
+ fprintf (fdopen (err, "a"), "In execvp of %s: %s\n",
+ exec_file, msg);
+ }
+
+ _exit (EXIT_FAILURE);
+
+ /* Not reached. */
+ return -1;
+}
+#endif
+
+#ifdef HAVE_START_CHILD
static SCM
scm_open_process (SCM mode, SCM prog, SCM args)
#define FUNC_NAME "open-process"
@@ -1252,7 +1338,7 @@ scm_open_process (SCM mode, SCM prog, SCM args)
int pid;
char *exec_file;
char **exec_argv;
- int max_fd = 1024;
+ SCM read_port = SCM_BOOL_F, write_port = SCM_BOOL_F;
exec_file = scm_to_locale_string (prog);
exec_argv = scm_i_allocate_string_pointers (scm_cons (prog, args));
@@ -1301,15 +1387,8 @@ scm_open_process (SCM mode, SCM prog, SCM args)
in = SCM_FPORT_FDES (port);
}
-#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_NOFILE)
- {
- struct rlimit lim = { 0, 0 };
- if (getrlimit (RLIMIT_NOFILE, &lim) == 0)
- max_fd = lim.rlim_cur;
- }
-#endif
-
- pid = fork ();
+ pid = start_child (exec_file, exec_argv, reading, c2p, writing, p2c,
+ in, out, err);
if (pid == -1)
{
@@ -1329,85 +1408,24 @@ scm_open_process (SCM mode, SCM prog, SCM args)
SCM_SYSERROR;
}
- if (pid)
- /* Parent. */
- {
- SCM read_port = SCM_BOOL_F, write_port = SCM_BOOL_F;
-
- /* There is no sense in catching errors on close(). */
- if (reading)
- {
- close (c2p[1]);
- read_port = scm_fdes_to_port (c2p[0], "r0", sym_read_pipe);
- }
- if (writing)
- {
- close (p2c[0]);
- write_port = scm_fdes_to_port (p2c[1], "w0", sym_write_pipe);
- }
-
- return scm_values
- (scm_list_3 (read_port, write_port, scm_from_int (pid)));
- }
-
- /* The child. */
+ /* There is no sense in catching errors on close(). */
if (reading)
- close (c2p[0]);
- if (writing)
- close (p2c[1]);
-
- /* Close all file descriptors in ports inherited from the parent
- except for in, out, and err. Heavy-handed, but robust. */
- while (max_fd--)
- if (max_fd != in && max_fd != out && max_fd != err)
- close (max_fd);
-
- /* Ignore errors on these open() calls. */
- if (in == -1)
- in = open ("/dev/null", O_RDONLY);
- if (out == -1)
- out = open ("/dev/null", O_WRONLY);
- if (err == -1)
- err = open ("/dev/null", O_WRONLY);
-
- if (in > 0)
{
- if (out == 0)
- do out = dup (out); while (errno == EINTR);
- if (err == 0)
- do err = dup (err); while (errno == EINTR);
- do dup2 (in, 0); while (errno == EINTR);
- close (in);
+ close (c2p[1]);
+ read_port = scm_fdes_to_port (c2p[0], "r0", sym_read_pipe);
}
- if (out > 1)
- {
- if (err == 1)
- do err = dup (err); while (errno == EINTR);
- do dup2 (out, 1); while (errno == EINTR);
- close (out);
- }
- if (err > 2)
- {
- do dup2 (err, 2); while (errno == EINTR);
- close (err);
- }
-
- execvp (exec_file, exec_argv);
-
- /* The exec failed! There is nothing sensible to do. */
- if (err > 0)
+ if (writing)
{
- char *msg = strerror (errno);
- fprintf (fdopen (err, "a"), "In execlp of %s: %s\n",
- exec_file, msg);
+ close (p2c[0]);
+ write_port = scm_fdes_to_port (p2c[1], "w0", sym_write_pipe);
}
- _exit (EXIT_FAILURE);
- /* Not reached. */
- return SCM_BOOL_F;
+ return scm_values (scm_list_3 (read_port,
+ write_port,
+ scm_from_int (pid)));
}
#undef FUNC_NAME
-#endif /* HAVE_FORK */
+#endif /* HAVE_START_CHILD */
#ifdef __MINGW32__
# include "win32-uname.h"
@@ -2215,13 +2233,13 @@ SCM_DEFINE (scm_gethostname, "gethostname", 0, 0, 0,
#endif /* HAVE_GETHOSTNAME */
-#ifdef HAVE_FORK
+#ifdef HAVE_START_CHILD
static void
scm_init_popen (void)
{
scm_c_define_gsubr ("open-process", 2, 0, 1, scm_open_process);
}
-#endif
+#endif /* HAVE_START_CHILD */
void
scm_init_posix ()
@@ -2320,11 +2338,13 @@ scm_init_posix ()
#ifdef HAVE_FORK
scm_add_feature ("fork");
+#endif /* HAVE_FORK */
+#ifdef HAVE_START_CHILD
scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
"scm_init_popen",
(scm_t_extension_init_func) scm_init_popen,
NULL);
-#endif /* HAVE_FORK */
+#endif /* HAVE_START_CHILD */
}
/*
- [Guile-commits] 24/27: Use non-deprecated HAVE_STRUCT_TM_TM_ZONE, (continued)
- [Guile-commits] 24/27: Use non-deprecated HAVE_STRUCT_TM_TM_ZONE, Andy Wingo, 2016/07/25
- [Guile-commits] 07/27: More specific status:exit-val et al compilation guards, Andy Wingo, 2016/07/25
- [Guile-commits] 12/27: Add popen feature, Andy Wingo, 2016/07/25
- [Guile-commits] 10/27: Rename win32-uname.[ch] to posix-w32.[ch], Andy Wingo, 2016/07/25
- [Guile-commits] 16/27: Update uname implementation in posix-w32, Andy Wingo, 2016/07/25
- [Guile-commits] 22/27: Gnulib: Add dirname-lgpl., Andy Wingo, 2016/07/25
- [Guile-commits] 14/27: Fix MinGW build error, Andy Wingo, 2016/07/25
- [Guile-commits] 06/27: getaffinity, setaffinity docstring cleanup, Andy Wingo, 2016/07/25
- [Guile-commits] 13/27: Update NEWS, Andy Wingo, 2016/07/25
- [Guile-commits] 26/27: Fix --without-threads against threaded BDW-GC, Andy Wingo, 2016/07/25
- [Guile-commits] 08/27: Factor start_child out of open_process,
Andy Wingo <=
- [Guile-commits] 21/27: doc: Add unquote and unquote-splicing examples., Andy Wingo, 2016/07/25
- [Guile-commits] 23/27: Use gnulib for basename / dirname, Andy Wingo, 2016/07/25
- [Guile-commits] 15/27: Fix unused static variables in net_db.c, Andy Wingo, 2016/07/25
- [Guile-commits] 25/27: Reimplement null-threads as inline functions, Andy Wingo, 2016/07/25
- [Guile-commits] 18/27: Allow mkstemp! to have optional "mode" argument, Andy Wingo, 2016/07/25
- [Guile-commits] 20/27: Untabify posix-w32.c, Andy Wingo, 2016/07/25
- [Guile-commits] 11/27: Add POSIX shims for MinGW, Andy Wingo, 2016/07/25
- [Guile-commits] 19/27: Improve process handling on MS-Windows, Andy Wingo, 2016/07/25