diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index b09fc36dee0..7e057401fab 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -45,7 +45,7 @@ pub struct Command { // other keys. program: CString, args: Vec, - argv: Vec<*const c_char>, + argv: Argv, env: CommandEnv, cwd: Option, @@ -58,6 +58,12 @@ pub struct Command { stderr: Option, } +// Create a new type for argv, so that we can make it `Send` +struct Argv(Vec<*const c_char>); + +// It is safe to make Argv Send, because it contains pointers to memory owned by `Command.args` +unsafe impl Send for Argv {} + // passed back to std::process with the pipes connected to the child, if any // were requested pub struct StdioPipes { @@ -87,17 +93,12 @@ pub enum Stdio { Fd(FileDesc), } -// Command is not Send by default due to the Command.argv field containing a raw pointers. However -// it is safe to implement Send, because anyway, these pointers point to memory owned by the -// Command.args field. -unsafe impl Send for Command {} - impl Command { pub fn new(program: &OsStr) -> Command { let mut saw_nul = false; let program = os2c(program, &mut saw_nul); Command { - argv: vec![program.as_ptr(), ptr::null()], + argv: Argv(vec![program.as_ptr(), ptr::null()]), program, args: Vec::new(), env: Default::default(), @@ -116,8 +117,8 @@ impl Command { // Overwrite the trailing NULL pointer in `argv` and then add a new null // pointer. let arg = os2c(arg, &mut self.saw_nul); - self.argv[self.args.len() + 1] = arg.as_ptr(); - self.argv.push(ptr::null()); + self.argv.0[self.args.len() + 1] = arg.as_ptr(); + self.argv.0.push(ptr::null()); // Also make sure we keep track of the owned value to schedule a // destructor for this memory. @@ -138,7 +139,7 @@ impl Command { self.saw_nul } pub fn get_argv(&self) -> &Vec<*const c_char> { - &self.argv + &self.argv.0 } #[allow(dead_code)]