@@ -33,6 +33,41 @@ bool IsFifoDescriptor(int fd) {
3333 return (ret == 0 ) && ((info.st_mode & S_IFMT) == S_IFIFO);
3434}
3535
36+ bool SetNonBlockingFd (int fd) {
37+ int flags = fcntl (fd, F_GETFL, 0 );
38+ if (!(flags & O_NONBLOCK)) {
39+ int ret = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
40+ if (ret < 0 )
41+ return false ;
42+ }
43+ return true ;
44+ }
45+
46+ bool SetCloseOnExecFd (int fd) {
47+ int flags = fcntl (fd, F_GETFD, 0 );
48+ if (!(flags & FD_CLOEXEC)) {
49+ int ret = fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
50+ if (ret < 0 )
51+ return false ;
52+ }
53+ return true ;
54+ }
55+
56+ // Duplicate the descriptor and make the result non-blocking and
57+ // close-on-exec.
58+ bool DuplicateDescriptor (int from_fd, int * to_fd) {
59+ int new_fd = dup (from_fd);
60+ if (new_fd < 0 ) {
61+ return false ;
62+ }
63+ if (!SetNonBlockingFd (new_fd) || !SetCloseOnExecFd (new_fd)) {
64+ ::close (new_fd);
65+ return false ;
66+ }
67+ *to_fd = new_fd;
68+ return true ;
69+ }
70+
3671// Implementation of Jobserver::Client for Posix systems
3772class PosixJobserverClient : public Jobserver ::Client {
3873 public:
@@ -77,6 +112,28 @@ class PosixJobserverClient : public Jobserver::Client {
77112 (void )ret; // Nothing can be done in case of error here.
78113 }
79114
115+ // Initialize instance with two explicit pipe file descriptors.
116+ bool InitWithPipeFds (int read_fd, int write_fd, std::string* error) {
117+ // Verify that the file descriptors belong to FIFOs.
118+ if (!IsFifoDescriptor (read_fd) || !IsFifoDescriptor (write_fd)) {
119+ *error = " Invalid file descriptors" ;
120+ return false ;
121+ }
122+ // Duplicate the file descriptors to make then non-blocking, and
123+ // close-on-exec. This is important because the original descriptors
124+ // might be inherited by sub-processes of this client.
125+ if (!DuplicateDescriptor (read_fd, &read_fd_)) {
126+ *error = " Could not duplicate read descriptor" ;
127+ return false ;
128+ }
129+ if (!DuplicateDescriptor (write_fd, &write_fd_)) {
130+ *error = " Could not duplicate write descriptor" ;
131+ // Let destructor close read_fd_.
132+ return false ;
133+ }
134+ return true ;
135+ }
136+
80137 // Initialize with FIFO file path.
81138 bool InitWithFifo (const std::string& fifo_path, std::string* error) {
82139 if (fifo_path.empty ()) {
@@ -122,6 +179,8 @@ std::unique_ptr<Jobserver::Client> Jobserver::Client::Create(
122179 auto client = std::unique_ptr<PosixJobserverClient>(new PosixJobserverClient);
123180 if (config.mode == Jobserver::Config::kModePosixFifo ) {
124181 success = client->InitWithFifo (config.path , error);
182+ } else if (config.mode == Jobserver::Config::kModePipe ) {
183+ success = client->InitWithPipeFds (config.read_fd , config.write_fd , error);
125184 } else {
126185 *error = " Unsupported jobserver mode" ;
127186 }
0 commit comments