From 80062128fea1c576dd465f8278445a3cccd04161 Mon Sep 17 00:00:00 2001 From: Pat Maddox Date: Fri, 30 Jan 2026 03:33:23 -0800 Subject: [PATCH] jobserver: Support GNU Make 4.3+ fifo jobserver format GNU Make 4.3+ uses named pipes for the jobserver, with the format --jobserver-auth=fifo:/path/to/pipe instead of the traditional --jobserver-auth=R,W format using inherited file descriptors. Prior to this, the test suite failed with: gmake: warning: -j10 forced in submake: resetting jobserver mode. redo x Traceback (most recent call last): File "apenwarr-redo/default.jj/bin/redo", line 10, in redo.cmd_redo.main() File "apenwarr-redo/default.jj/bin/../redo/cmd_redo.py", line 107, in main jobserver.setup(j) File "apenwarr-redo/default.jj/bin/../redo/jobserver.py", line 230, in setup (a, b) = arg.split(',', 1) ^^^^^^ ValueError: not enough values to unpack (expected 2, got 1) gmake: *** [Makefile:7: y] Error 1 --- redo/jobserver.py | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/redo/jobserver.py b/redo/jobserver.py index 6dc30b6..874859f 100644 --- a/redo/jobserver.py +++ b/redo/jobserver.py @@ -227,19 +227,33 @@ def setup(maxjobs): if ofs >= 0: s = flags[ofs+len(FIND):] (arg, junk) = s.split(' ', 1) - (a, b) = arg.split(',', 1) - a = atoi(a) - b = atoi(b) - if a <= 0 or b <= 0: - logs.err('invalid --jobserver-auth: %r\n' % arg) - raise helpers.ImmediateReturn(200) - if not helpers.fd_exists(a) or not helpers.fd_exists(b): - logs.err('broken --jobserver-auth from parent process:\n') - logs.err(' using GNU make? prefix your Makefile rule with "+"\n') - logs.err( - ' otherwise, see ' + - 'https://redo.rtfd.io/en/latest/FAQParallel/#MAKEFLAGS\n') - raise helpers.ImmediateReturn(200) + if arg.startswith('fifo:'): + # GNU Make 4.3+ named pipe jobserver format: fifo:/path/to/pipe + fifo_path = arg[5:] + try: + # Open the named pipe for both reading and writing. + # O_RDWR avoids blocking that would occur with O_RDONLY. + fd = os.open(fifo_path, os.O_RDWR) + a = fd + b = fd + except OSError as e: + logs.err('cannot open jobserver fifo %r: %s\n' % (fifo_path, e)) + raise helpers.ImmediateReturn(200) + else: + # Traditional pipe jobserver format: R,W (two file descriptors) + (a, b) = arg.split(',', 1) + a = atoi(a) + b = atoi(b) + if a <= 0 or b <= 0: + logs.err('invalid --jobserver-auth: %r\n' % arg) + raise helpers.ImmediateReturn(200) + if not helpers.fd_exists(a) or not helpers.fd_exists(b): + logs.err('broken --jobserver-auth from parent process:\n') + logs.err(' using GNU make? prefix your Makefile rule with "+"\n') + logs.err( + ' otherwise, see ' + + 'https://redo.rtfd.io/en/latest/FAQParallel/#MAKEFLAGS\n') + raise helpers.ImmediateReturn(200) if maxjobs == 1: # user requested exactly one token, which means they want to # serialize us, even if the parent redo is running in parallel.