Skip to content

Comments

[LLVM] Remove the requirement for named pipe in jobserver#169154

Merged
mgorny merged 2 commits intollvm:mainfrom
mgorny:jobserver-nonfifo
Dec 16, 2025
Merged

[LLVM] Remove the requirement for named pipe in jobserver#169154
mgorny merged 2 commits intollvm:mainfrom
mgorny:jobserver-nonfifo

Conversation

@mgorny
Copy link
Member

@mgorny mgorny commented Nov 22, 2025

Remove the requirement that the jobserver "fifo" is actually a named pipe. Named pipes are essentially stateless, and therefore carry a high risk of a killed process leaving the server with no tokens left, and no clear way to reclaim them. Therefore, multiple jobserver implementations use FUSE instead:

This is compatible with GNU make and Ninja, since they do not check the file type, and seems to be the only solution that can achieve state tracking while preserving compatibility.

CC @amonakov

@llvmbot
Copy link
Member

llvmbot commented Nov 22, 2025

@llvm/pr-subscribers-llvm-support

Author: Michał Górny (mgorny)

Changes

Remove the requirement that the jobserver "fifo" is actually a named pipe. Named pipes are essentially stateless, and therefore carry a high risk of a killed process leaving the server with no tokens left, and no clear way to reclaim them. Therefore, multiple jobserver implementations use FUSE instead:

This is compatible with GNU make and Ninja, since they do not check the file type, and seems to be the only solution that can achieve state tracking while preserving compatibility.

CC @amonakov


Full diff: https://github.com/llvm/llvm-project/pull/169154.diff

1 Files Affected:

  • (modified) llvm/lib/Support/Unix/Jobserver.inc (+1-9)
diff --git a/llvm/lib/Support/Unix/Jobserver.inc b/llvm/lib/Support/Unix/Jobserver.inc
index 53bf7f288ca1f..300fb5e55045e 100644
--- a/llvm/lib/Support/Unix/Jobserver.inc
+++ b/llvm/lib/Support/Unix/Jobserver.inc
@@ -19,14 +19,6 @@
 #include <unistd.h>
 
 namespace {
-/// Returns true if the given file descriptor is a FIFO (named pipe).
-bool isFifo(int FD) {
-  struct stat StatBuf;
-  if (::fstat(FD, &StatBuf) != 0)
-    return false;
-  return S_ISFIFO(StatBuf.st_mode);
-}
-
 /// Returns true if the given file descriptors are valid.
 bool areFdsValid(int ReadFD, int WriteFD) {
   if (ReadFD == -1 || WriteFD == -1)
@@ -75,7 +67,7 @@ JobserverClientImpl::JobserverClientImpl(const JobserverConfig &Config) {
   case JobserverConfig::PosixFifo:
     // Open the FIFO for reading. It must be non-blocking and close-on-exec.
     ReadFD = ::open(Config.Path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC);
-    if (ReadFD < 0 || !isFifo(ReadFD)) {
+    if (ReadFD < 0) {
       if (ReadFD >= 0)
         ::close(ReadFD);
       ReadFD = -1;

@yxsamliu
Copy link
Collaborator

yxsamliu commented Dec 1, 2025

This change looks good functionally, but I think it leaves some confusing naming and comments behind.

Previously, JobserverConfig::PosixFifo was tightly coupled to a real POSIX FIFO (we enforced S_ISFIFO), so the fifo naming and comments in this code matched the actual kernel object. Now that we intentionally accept any endpoint that implements the jobserver token protocol (including FUSE files or CUSE character devices), the FIFO terminology becomes misleading: it's really 'FIFO-compatible endpoint as described by fifo: in MAKEFLAGS', not necessarily a kernel FIFO.

It would be clearer to future readers if we adjusted the naming/comments in a follow-up:

  • In Unix/Jobserver.inc:

    • The constructor comment around L40-L44 ("For FIFO-based jobservers, it opens the named pipe") and the comment on release() ("For FIFO-based jobservers, the write FD might not be open yet") should be reworded to something like 'FIFO-style' or 'path-based jobservers'.
    • The member FifoPath and related debug messages ("opening FIFO", "Opened FIFO as new WriteFD") could be renamed to something like EndpointPath or JobserverPath.
  • In Jobserver.cpp:

    • The FifoPath local and JobserverConfig::FifoPath member share the same assumption and may deserve a more generic name or an updated comment explaining that fifo: is a protocol tag, not a strict type guarantee.

@yxsamliu
Copy link
Collaborator

yxsamliu commented Dec 1, 2025

It might be worth adding a small regression test to lock in the new behavior around fifo: endpoints.

Right now the Unix jobserver tests (JobserverClientTest.UnixClientFifo and the JobserverStrategyTest cases) only exercise the "happy path" with a real FIFO created by ScopedFifo. Before this patch, JobserverClientImpl would reject any --jobserver-auth=fifo:PATH that did not point to a S_ISFIFO object; after this patch we intentionally accept non-FIFO endpoints as long as open() succeeds.

To make that intent explicit and prevent future regressions, I would suggest adding a test alongside UnixClientFifo that:

  • Creates a regular temporary file (or uses createTemporaryFile but does not replace it with a FIFO).
  • Sets MAKEFLAGS to --jobserver-auth=fifo: using ScopedEnvironment.
  • Calls JobserverClient::getInstance() and asserts we get a non-null client and that it is considered valid (no "invalid FIFO" rejection).

This would clearly document that fifo: is now a protocol tag rather than a strict POSIX FIFO requirement, and that we deliberately allow FUSE/CUSE-backed implementations presenting themselves under a fifo: URL.

Remove the requirement that the jobserver "fifo" is actually a named
pipe.  Named pipes are essentially stateless, and therefore carry a high
risk of a killed process leaving the server with no tokens left, and no
clear way to reclaim them.  Therefore, multiple jobserver
implementations use FUSE instead:

- [nixos-jobserver](NixOS/nixpkgs#314888) (WIP)
  uses simple file on FUSE

- [steve](https://gitweb.gentoo.org/proj/steve.git) uses a character
  device via CUSE

- [guildmaster](https://codeberg.org/amonakov/guildmaster) uses
  a character device via CUSE

This is compatible with GNU make and Ninja, since they do not check
the file type, and seems to be the only solution that can achieve
state tracking while preserving compatibility.

Signed-off-by: Michał Górny <[email protected]>
@mgorny mgorny force-pushed the jobserver-nonfifo branch from 762cdd3 to 32e2acb Compare December 1, 2025 18:52
@mgorny
Copy link
Member Author

mgorny commented Dec 1, 2025

Rebased and added a test so far. I've just copied the whole logic from UnixClientFifo test, since it also works fine for an empty file.

@thesamesam
Copy link
Member

@yxsamliu ping

Copy link
Collaborator

@yxsamliu yxsamliu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks

@mgorny mgorny merged commit 13f7b30 into llvm:main Dec 16, 2025
10 checks passed
@mgorny mgorny deleted the jobserver-nonfifo branch December 16, 2025 18:42
mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Dec 19, 2025
Remove the requirement that the jobserver "fifo" is actually a named
pipe. Named pipes are essentially stateless, and therefore carry a high
risk of a killed process leaving the server with no tokens left, and no
clear way to reclaim them. Therefore, multiple jobserver implementations
use FUSE instead:

- [nixos-jobserver](NixOS/nixpkgs#314888) (WIP)
uses simple file on FUSE

- [steve](https://gitweb.gentoo.org/proj/steve.git) uses a character
device via CUSE

- [guildmaster](https://codeberg.org/amonakov/guildmaster) uses a
character device via CUSE

This is compatible with GNU make and Ninja, since they do not check the
file type, and seems to be the only solution that can achieve state
tracking while preserving compatibility.

CC @amonakov

---------

Signed-off-by: Michał Górny <[email protected]>
valadaptive pushed a commit to valadaptive/llvm-project that referenced this pull request Dec 24, 2025
Remove the requirement that the jobserver "fifo" is actually a named
pipe. Named pipes are essentially stateless, and therefore carry a high
risk of a killed process leaving the server with no tokens left, and no
clear way to reclaim them. Therefore, multiple jobserver implementations
use FUSE instead:

- [nixos-jobserver](NixOS/nixpkgs#314888) (WIP)
uses simple file on FUSE

- [steve](https://gitweb.gentoo.org/proj/steve.git) uses a character
device via CUSE

- [guildmaster](https://codeberg.org/amonakov/guildmaster) uses a
character device via CUSE

This is compatible with GNU make and Ninja, since they do not check the
file type, and seems to be the only solution that can achieve state
tracking while preserving compatibility.

CC @amonakov

---------

Signed-off-by: Michał Górny <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants