Skip to content

Commit 194ccdc

Browse files
committed
Fix Client::configure* on unix
Fixed #99
1 parent c0c2898 commit 194ccdc

File tree

1 file changed

+43
-46
lines changed

1 file changed

+43
-46
lines changed

src/unix.rs

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::io::{self, Read, Write};
66
use std::mem;
77
use std::mem::MaybeUninit;
88
use std::os::unix::prelude::*;
9-
use std::path::{Path, PathBuf};
9+
use std::path::Path;
1010
use std::process::Command;
1111
use std::ptr;
1212
use std::sync::{
@@ -17,17 +17,15 @@ use std::thread::{self, Builder, JoinHandle};
1717
use std::time::Duration;
1818

1919
#[derive(Debug)]
20-
pub enum Client {
21-
/// `--jobserver-auth=R,W`
22-
Pipe { read: File, write: File },
23-
/// `--jobserver-auth=fifo:PATH`
24-
Fifo {
25-
file: File,
26-
path: PathBuf,
27-
/// it can only go from false -> true but not the other way around, since that
28-
/// could cause a race condition.
29-
is_non_blocking: AtomicBool,
30-
},
20+
pub struct Client {
21+
read: File,
22+
write: Option<File>,
23+
/// If path is not None, then a fifo jobserver is created.
24+
path: Option<Box<Path>>,
25+
supports_non_blocking: bool,
26+
/// it can only go from false -> true but not the other way around, since that
27+
/// could cause a race condition.
28+
is_non_blocking: AtomicBool,
3129
}
3230

3331
#[derive(Debug)]
@@ -117,9 +115,11 @@ impl Client {
117115
.open(path)
118116
.map_err(|err| FromEnvErrorInner::CannotOpenPath(path_str.to_string(), err))?;
119117

120-
Ok(Some(Client::Fifo {
121-
file,
122-
path: path.into(),
118+
Ok(Some(Client {
119+
read: file,
120+
write: None,
121+
path: Some(path.into()),
122+
supports_non_blocking: true,
123123
is_non_blocking: AtomicBool::new(false),
124124
}))
125125
}
@@ -174,41 +174,42 @@ impl Client {
174174
//
175175
// I tested this on macOS 14 and Linux 6.5.13
176176
#[cfg(target_os = "linux")]
177-
if let Ok(Some(jobserver)) =
177+
if let Ok(Some(mut jobserver)) =
178178
Self::from_fifo(&format!("fifo:/dev/fd/{}", read.as_raw_fd()))
179179
{
180+
jobserver.path.take();
180181
return Ok(Some(jobserver));
181182
}
182183
}
183184
}
184185

185-
Ok(Some(Client::Pipe {
186+
Ok(Some(Client {
186187
read: clone_fd_and_set_cloexec(read)?,
187-
write: clone_fd_and_set_cloexec(write)?,
188+
write: Some(clone_fd_and_set_cloexec(write)?),
189+
path: None,
190+
supports_non_blocking: false,
191+
is_non_blocking: AtomicBool::new(false),
188192
}))
189193
}
190194

191195
unsafe fn from_fds(read: c_int, write: c_int) -> Client {
192-
Client::Pipe {
196+
Client {
193197
read: File::from_raw_fd(read),
194-
write: File::from_raw_fd(write),
198+
write: Some(File::from_raw_fd(write)),
199+
path: None,
200+
supports_non_blocking: false,
201+
is_non_blocking: AtomicBool::new(false),
195202
}
196203
}
197204

198205
/// Gets the read end of our jobserver client.
199206
fn read(&self) -> &File {
200-
match self {
201-
Client::Pipe { read, .. } => read,
202-
Client::Fifo { file, .. } => file,
203-
}
207+
&self.read
204208
}
205209

206210
/// Gets the write end of our jobserver client.
207211
fn write(&self) -> &File {
208-
match self {
209-
Client::Pipe { write, .. } => write,
210-
Client::Fifo { file, .. } => file,
211-
}
212+
self.write.as_ref().unwrap_or(&self.read)
212213
}
213214

214215
pub fn acquire(&self) -> io::Result<Acquired> {
@@ -285,18 +286,15 @@ impl Client {
285286
pub fn try_acquire(&self) -> io::Result<Option<Acquired>> {
286287
let mut buf = [0];
287288

288-
let (mut fifo, is_non_blocking) = match self {
289-
Self::Fifo {
290-
file,
291-
is_non_blocking,
292-
..
293-
} => (file, is_non_blocking),
294-
_ => return Err(io::ErrorKind::Unsupported.into()),
295-
};
289+
if !self.supports_non_blocking {
290+
return Err(io::ErrorKind::Unsupported.into());
291+
}
292+
293+
let mut fifo = self.read();
296294

297-
if !is_non_blocking.load(Ordering::Relaxed) {
295+
if !self.is_non_blocking.load(Ordering::Relaxed) {
298296
set_nonblocking(fifo.as_raw_fd(), true)?;
299-
is_non_blocking.store(true, Ordering::Relaxed);
297+
self.is_non_blocking.store(true, Ordering::Relaxed);
300298
}
301299

302300
loop {
@@ -333,10 +331,10 @@ impl Client {
333331
}
334332

335333
pub fn string_arg(&self) -> String {
336-
match self {
337-
Client::Pipe { read, write } => format!("{},{}", read.as_raw_fd(), write.as_raw_fd()),
338-
Client::Fifo { path, .. } => format!("fifo:{}", path.to_str().unwrap()),
339-
}
334+
self.path
335+
.as_deref()
336+
.map(|path| format!("fifo:{}", path.display()))
337+
.unwrap_or_else(|| format!("{},{}", self.read().as_raw_fd(), self.write().as_raw_fd()))
340338
}
341339

342340
pub fn available(&self) -> io::Result<usize> {
@@ -346,12 +344,11 @@ impl Client {
346344
}
347345

348346
pub fn configure(&self, cmd: &mut Command) {
349-
match self {
347+
if self.path.is_some() {
350348
// We `File::open`ed it when inheriting from environment,
351349
// so no need to set cloexec for fifo.
352-
Client::Fifo { .. } => return,
353-
Client::Pipe { .. } => {}
354-
};
350+
return;
351+
}
355352
// Here we basically just want to say that in the child process
356353
// we'll configure the read/write file descriptors to *not* be
357354
// cloexec, so they're inherited across the exec and specified as

0 commit comments

Comments
 (0)