]> git.ipfire.org Git - thirdparty/make.git/commitdiff
[SV 66499] Detect jobserver values that are too large master
authorPaul Smith <psmith@gnu.org>
Sun, 8 Dec 2024 21:31:54 +0000 (16:31 -0500)
committerPaul Smith <psmith@gnu.org>
Mon, 9 Dec 2024 04:30:37 +0000 (23:30 -0500)
Set the jobserver pipe to non-blocking before writing tokens; if a
token write fails the user's jobserver value is too large so fail.

Original implementation: Dmitry Goncharov <dgoncharov@users.sf.net>

* src/posixos.c (set_blocking): Split into force_blocking() which
always enables/disables blocking; set_blocking() may call it.
(jobserver_setup): Set the write side of the pipe to non-blocking
before writing tokens.  If it fails with EAGAIN we know the pipe
is full: create a fatal error.
* tests/scripts/features/jobserver: Test a too-large jobserver.

src/posixos.c
tests/scripts/features/jobserver

index 163ca6ed45e1d4afe862d10f999e9214513048b8..27b69798703d141e8c310a9f14136476a9ee22c6 100644 (file)
@@ -122,10 +122,8 @@ make_job_rfd ()
 }
 
 static void
-set_blocking (int fd, int blocking)
+force_blocking (int fd, int blocking)
 {
-  /* If we're not using pselect() don't change the blocking.  */
-#ifdef HAVE_PSELECT
   int flags;
   EINTRLOOP (flags, fcntl (fd, F_GETFL));
   if (flags >= 0)
@@ -136,6 +134,14 @@ set_blocking (int fd, int blocking)
       if (r < 0)
         pfatal_with_name ("fcntl(O_NONBLOCK)");
     }
+}
+
+static void
+set_blocking (int fd, int blocking)
+{
+  /* If we're not using pselect() don't change the blocking.  */
+#ifdef HAVE_PSELECT
+  force_blocking (fd, blocking);
 #else
   (void) fd;
   (void) blocking;
@@ -145,7 +151,7 @@ set_blocking (int fd, int blocking)
 unsigned int
 jobserver_setup (int slots, const char *style)
 {
-  int r;
+  int r, k;
 
   /* This function sets up the root jobserver.  */
   job_root = 1;
@@ -211,12 +217,21 @@ jobserver_setup (int slots, const char *style)
   if (make_job_rfd () < 0)
     pfatal_with_name (_("duping jobs pipe"));
 
-  while (slots--)
+  /* Set the write side of the pipe to non blocking in case the number of
+     slots specified by the user exceeds pipe capacity.  */
+  force_blocking (job_fds[1], 0);
+  for (k = 0; k < slots; ++k)
     {
       EINTRLOOP (r, write (job_fds[1], &token, 1));
       if (r != 1)
-        pfatal_with_name (_("init jobserver pipe"));
+        {
+          if (errno != EAGAIN)
+            pfatal_with_name (_("init jobserver pipe"));
+
+          ONN (fatal, NILF, _("requested job count (%d) is larger than system limit (%d)"), slots+1, k);
+        }
     }
+  force_blocking (job_fds[1], 1);
 
   /* When using pselect() we want the read to be non-blocking.  */
   set_blocking (job_fds[0], 0);
index 50d51f80f7fbbdd21cde5097cd7457184003eba2..5bdf4a5eb5feb69fd65d69c334a59627ad2ab8db 100644 (file)
@@ -211,4 +211,15 @@ all:;@echo "$$MAKEFLAGS"
   run_make_test(q!all:;@echo hi!, "", "#MAKE#: cannot open jobserver nosuchfile: $ERR_no_such_file\n#MAKE#: $j1err\nhi\n");
 }
 
+if ($port_type eq 'UNIX') {
+    # sv 66499. The specified number of jobs exceeds pipe capacity.
+    run_make_test(q!
+all:; $(info hello, world)
+    !, '-j688777', '/requested job count \(688777\) is larger than system limit/', 512);
+
+    run_make_test(q!
+all:; $(info hello, world)
+    !, '-j688777 --jobserver-style=pipe', '/requested job count \(688777\) is larger than system limit/', 512);
+}
+
 1;