summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2013-09-15 15:05:18 -0400
committerPaul Smith <psmith@gnu.org>2013-09-15 15:21:33 -0400
commita4d8444b594e53b13659a9f2c64424418f255e27 (patch)
tree13315e9de3f19f3a144774a008bd3100633a31c3 /main.c
parent0a81d50d66565fd3e930fadaadc4a5cb9381d840 (diff)
downloadgunmake-a4d8444b594e53b13659a9f2c64424418f255e27.tar.gz
[SV 39934] Verify jobserver FDs before something else uses them.
Diffstat (limited to 'main.c')
-rw-r--r--main.c178
1 files changed, 94 insertions, 84 deletions
diff --git a/main.c b/main.c
index 0fdf501..bfc125c 100644
--- a/main.c
+++ b/main.c
@@ -1393,6 +1393,15 @@ main (int argc, char **argv, char **envp)
decode_switches (argc, argv, 0);
+ /* Figure out the level of recursion. */
+ {
+ struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME));
+ if (v && v->value[0] != '\0' && v->value[0] != '-')
+ makelevel = (unsigned int) atoi (v->value);
+ else
+ makelevel = 0;
+ }
+
#ifdef WINDOWS32
if (suspend_flag)
{
@@ -1468,6 +1477,91 @@ main (int argc, char **argv, char **envp)
#endif /* WINDOWS32 */
#endif
+#ifdef MAKE_JOBSERVER
+ /* If the jobserver-fds option is seen, make sure that -j is reasonable.
+ This can't be usefully set in the makefile, and we want to verify the
+ FDs are valid before any other aspect of make has a chance to start
+ using them for something else. */
+
+ if (jobserver_fds)
+ {
+ const char *cp;
+ unsigned int ui;
+
+ for (ui=1; ui < jobserver_fds->idx; ++ui)
+ if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui]))
+ fatal (NILF, _("internal error: multiple --jobserver-fds options"));
+
+ /* Now parse the fds string and make sure it has the proper format. */
+
+ cp = jobserver_fds->list[0];
+
+#ifdef WINDOWS32
+ if (! open_jobserver_semaphore (cp))
+ {
+ DWORD err = GetLastError ();
+ fatal (NILF, _("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"),
+ cp, err, map_windows32_error_to_string (err));
+ }
+ DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), cp));
+#else
+ if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
+ fatal (NILF,
+ _("internal error: invalid --jobserver-fds string '%s'"), cp);
+
+ DB (DB_JOBS,
+ (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
+#endif
+
+ /* The combination of a pipe + !job_slots means we're using the
+ jobserver. If !job_slots and we don't have a pipe, we can start
+ infinite jobs. If we see both a pipe and job_slots >0 that means the
+ user set -j explicitly. This is broken; in this case obey the user
+ (ignore the jobserver pipe for this make) but print a message.
+ If we've restarted, we already printed this the first time. */
+
+ if (job_slots > 0)
+ {
+ if (! restarts)
+ error (NILF, _("warning: -jN forced in submake: disabling jobserver mode."));
+ }
+#ifndef WINDOWS32
+#define FD_OK(_f) ((fcntl ((_f), F_GETFD) != -1) || (errno != EBADF))
+ /* Create a duplicate pipe, that will be closed in the SIGCHLD
+ handler. If this fails with EBADF, the parent has closed the pipe
+ on us because it didn't think we were a submake. If so, print a
+ warning then default to -j1. */
+ else if (!FD_OK (job_fds[0]) || !FD_OK (job_fds[1])
+ || (job_rfd = dup (job_fds[0])) < 0)
+ {
+ if (errno != EBADF)
+ pfatal_with_name (_("dup jobserver"));
+
+ error (NILF,
+ _("warning: jobserver unavailable: using -j1. Add '+' to parent make rule."));
+ job_slots = 1;
+ job_fds[0] = job_fds[1] = -1;
+ }
+#endif
+
+ if (job_slots > 0)
+ {
+#ifdef WINDOWS32
+ free_jobserver_semaphore ();
+#else
+ if (job_fds[0] >= 0)
+ close (job_fds[0]);
+ if (job_fds[1] >= 0)
+ close (job_fds[1]);
+#endif
+ job_fds[0] = job_fds[1] = -1;
+ free (jobserver_fds->list);
+ free (jobserver_fds);
+ jobserver_fds = 0;
+ }
+ }
+#endif
+
/* The extra indirection through $(MAKE_COMMAND) is done
for hysterical raisins. */
define_variable_cname ("MAKE_COMMAND", argv[0], o_default, 0);
@@ -1554,16 +1648,7 @@ main (int argc, char **argv, char **envp)
* at the wrong place when it was first evaluated.
*/
no_default_sh_exe = !find_and_set_default_shell (NULL);
-
#endif /* WINDOWS32 */
- /* Figure out the level of recursion. */
- {
- struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME));
- if (v != 0 && v->value[0] != '\0' && v->value[0] != '-')
- makelevel = (unsigned int) atoi (v->value);
- else
- makelevel = 0;
- }
/* Except under -s, always do -w in sub-makes and under -C. */
if (!silent_flag && (directories != 0 || makelevel > 0))
@@ -1851,81 +1936,6 @@ main (int argc, char **argv, char **envp)
#endif
#ifdef MAKE_JOBSERVER
- /* If the jobserver-fds option is seen, make sure that -j is reasonable. */
-
- if (jobserver_fds)
- {
- const char *cp;
- unsigned int ui;
-
- for (ui=1; ui < jobserver_fds->idx; ++ui)
- if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui]))
- fatal (NILF, _("internal error: multiple --jobserver-fds options"));
-
- /* Now parse the fds string and make sure it has the proper format. */
-
- cp = jobserver_fds->list[0];
-
-#ifdef WINDOWS32
- if (! open_jobserver_semaphore (cp))
- {
- DWORD err = GetLastError ();
- fatal (NILF, _("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"),
- cp, err, map_windows32_error_to_string (err));
- }
- DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), cp));
-#else
- if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
- fatal (NILF,
- _("internal error: invalid --jobserver-fds string '%s'"), cp);
-
- DB (DB_JOBS,
- (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
-#endif
-
- /* The combination of a pipe + !job_slots means we're using the
- jobserver. If !job_slots and we don't have a pipe, we can start
- infinite jobs. If we see both a pipe and job_slots >0 that means the
- user set -j explicitly. This is broken; in this case obey the user
- (ignore the jobserver pipe for this make) but print a message.
- If we've restarted, we already printed this the first time. */
-
- if (job_slots > 0)
- {
- if (! restarts)
- error (NILF, _("warning: -jN forced in submake: disabling jobserver mode."));
- }
-#ifndef WINDOWS32
- /* Create a duplicate pipe, that will be closed in the SIGCHLD
- handler. If this fails with EBADF, the parent has closed the pipe
- on us because it didn't think we were a submake. If so, print a
- warning then default to -j1. */
- else if ((job_rfd = dup (job_fds[0])) < 0)
- {
- if (errno != EBADF)
- pfatal_with_name (_("dup jobserver"));
-
- error (NILF,
- _("warning: jobserver unavailable: using -j1. Add '+' to parent make rule."));
- job_slots = 1;
- }
-#endif
-
- if (job_slots > 0)
- {
-#ifdef WINDOWS32
- free_jobserver_semaphore ();
-#else
- close (job_fds[0]);
- close (job_fds[1]);
-#endif
- job_fds[0] = job_fds[1] = -1;
- free (jobserver_fds->list);
- free (jobserver_fds);
- jobserver_fds = 0;
- }
- }
-
/* If we have >1 slot but no jobserver-fds, then we're a top-level make.
Set up the pipe and install the fds option for our children. */