-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Diagnostic: extend from_env function #52
Changes from 10 commits
23e8b7e
3275a9a
8b50514
6e047a5
621665f
1cd2091
39b2790
85fc976
a900301
9ca894f
ff334c2
65bf01a
c78d26d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,8 +29,8 @@ | |
//! | ||
//! // See API documentation for why this is `unsafe` | ||
//! let client = match unsafe { Client::from_env() } { | ||
//! Some(client) => client, | ||
//! None => panic!("client not configured"), | ||
//! Ok(client) => client, | ||
//! Err(_) => panic!("client not configured"), | ||
//! }; | ||
//! ``` | ||
//! | ||
|
@@ -151,6 +151,44 @@ struct HelperInner { | |
consumer_done: bool, | ||
} | ||
|
||
/// Error type for `from_env` function. | ||
#[derive(Debug)] | ||
pub enum ErrFromEnv { | ||
/// There isn't env var, that describes jobserver to inherit. | ||
IsNotConfigured, | ||
/// Cannot connect following this process's environment. | ||
PlatformSpecific { | ||
/// Error. | ||
err: io::Error, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @weihanglo It's possible that in practice we'll need to discern between different kinds of erros (e.g. "descriptors are closed" and everything else) to avoid bothering users with warnings too often. This PR, however, merges all the errors into a single There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. I'll try taking a look this week. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Maybe jobserver can have the error kind documented on docs.rs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for the late response. I think the change works fine with Cargo. Cargo can just ignore the jobserver if there are bad pipes. No harm to get this patch released on Cargo side I believe :) |
||
/// Name of gotten env var. | ||
env: &'static str, | ||
/// Value of gotten env var. | ||
var: String, | ||
}, | ||
} | ||
|
||
belovdv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
impl std::fmt::Display for ErrFromEnv { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
match self { | ||
ErrFromEnv::IsNotConfigured => { | ||
write!(f, "couldn't find relevant environment variable") | ||
} | ||
ErrFromEnv::PlatformSpecific { err, env, var } => { | ||
write!(f, "{err} ({env}={var}") | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl std::error::Error for ErrFromEnv { | ||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { | ||
match self { | ||
ErrFromEnv::IsNotConfigured => None, | ||
ErrFromEnv::PlatformSpecific { err, .. } => Some(err), | ||
} | ||
} | ||
} | ||
|
||
impl Client { | ||
/// Creates a new jobserver initialized with the given parallelism limit. | ||
/// | ||
|
@@ -197,8 +235,9 @@ impl Client { | |
/// # Return value | ||
/// | ||
/// If a jobserver was found in the environment and it looks correct then | ||
/// `Some` of the connected client will be returned. If no jobserver was | ||
/// found then `None` will be returned. | ||
/// `Ok` of the connected client will be returned. If no relevant env var | ||
/// was found then `Err(IsNotConfigured)` will be returned. In other cases | ||
/// `Err(PlatformSpecific)` will be returned. | ||
/// | ||
/// Note that on Unix the `Client` returned **takes ownership of the file | ||
/// descriptors specified in the environment**. Jobservers on Unix are | ||
|
@@ -211,6 +250,9 @@ impl Client { | |
/// with `CLOEXEC` so they're not automatically inherited by spawned | ||
/// children. | ||
/// | ||
/// There is a feature to configure, will this function check if provided | ||
/// files are actually pipes. | ||
/// | ||
/// # Safety | ||
/// | ||
/// This function is `unsafe` to call on Unix specifically as it | ||
|
@@ -227,28 +269,24 @@ impl Client { | |
/// | ||
/// Note, though, that on Windows it should be safe to call this function | ||
/// any number of times. | ||
pub unsafe fn from_env() -> Option<Client> { | ||
let var = match env::var("CARGO_MAKEFLAGS") | ||
.or_else(|_| env::var("MAKEFLAGS")) | ||
.or_else(|_| env::var("MFLAGS")) | ||
{ | ||
Ok(s) => s, | ||
Err(_) => return None, | ||
}; | ||
let mut arg = "--jobserver-fds="; | ||
let pos = match var.find(arg) { | ||
Some(i) => i, | ||
None => { | ||
arg = "--jobserver-auth="; | ||
match var.find(arg) { | ||
Some(i) => i, | ||
None => return None, | ||
} | ||
} | ||
}; | ||
pub unsafe fn from_env() -> Result<Client, ErrFromEnv> { | ||
belovdv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let (env, var) = ["CARGO_MAKEFLAGS", "MAKEFLAGS", "MFLAGS"] | ||
.iter() | ||
.map(|&env| env::var(env).map(|var| (env, var))) | ||
.find_map(|p| p.ok()) | ||
.ok_or(ErrFromEnv::IsNotConfigured)?; | ||
|
||
let (arg, pos) = ["--jobserver-fds=", "--jobserver-auth="] | ||
.iter() | ||
.map(|&arg| var.find(arg).map(|pos| (arg, pos))) | ||
.find_map(|pos| pos) | ||
.ok_or(ErrFromEnv::IsNotConfigured)?; | ||
|
||
let s = var[pos + arg.len()..].split(' ').next().unwrap(); | ||
imp::Client::open(s).map(|c| Client { inner: Arc::new(c) }) | ||
match imp::Client::open(s) { | ||
Ok(c) => Ok(Client { inner: Arc::new(c) }), | ||
Err(err) => Err(ErrFromEnv::PlatformSpecific { err, env, var }), | ||
} | ||
} | ||
|
||
/// Acquires a token from this jobserver client. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also not a good idea since features should be additive.
With this do_not_check_pipe feature,if one of the crate enables this, then every other crate is opt out of checking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise if one enables check then one uses smth different from pipe will fail. I'm not sure should be this option or not and, if should, how should it behave, imho it should be decided by maintainer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If checking or not checking the pipe-ness should be configurable, then it should probably be a runtime option passed to
from_env
.Not checking is the GNU Make behavior, checking catches errors in practice.