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.
-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)
int flags;
EINTRLOOP (flags, fcntl (fd, F_GETFL));
if (flags >= 0)
if (r < 0)
pfatal_with_name ("fcntl(O_NONBLOCK)");
}
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;
#else
(void) fd;
(void) blocking;
unsigned int
jobserver_setup (int slots, const char *style)
{
unsigned int
jobserver_setup (int slots, const char *style)
{
/* This function sets up the root jobserver. */
job_root = 1;
/* This function sets up the root jobserver. */
job_root = 1;
if (make_job_rfd () < 0)
pfatal_with_name (_("duping jobs pipe"));
if (make_job_rfd () < 0)
pfatal_with_name (_("duping jobs pipe"));
+ /* 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)
{
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);
/* When using pselect() we want the read to be non-blocking. */
set_blocking (job_fds[0], 0);
run_make_test(q!all:;@echo hi!, "", "#MAKE#: cannot open jobserver nosuchfile: $ERR_no_such_file\n#MAKE#: $j1err\nhi\n");
}
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);
+}
+