Skip to content

Commit 9e6ed17

Browse files
committed
make Command.argv Send on unix platforms
Implementing Send for a specific field rather than the whole struct is safer: if a field is changed/modified and becomes non-Send, we can catch it.
1 parent 831ff77 commit 9e6ed17

File tree

1 file changed

+11
-10
lines changed

1 file changed

+11
-10
lines changed

src/libstd/sys/unix/process/process_common.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub struct Command {
4545
// other keys.
4646
program: CString,
4747
args: Vec<CString>,
48-
argv: Vec<*const c_char>,
48+
argv: Argv,
4949
env: CommandEnv<DefaultEnvKey>,
5050

5151
cwd: Option<CString>,
@@ -58,6 +58,12 @@ pub struct Command {
5858
stderr: Option<Stdio>,
5959
}
6060

61+
// Create a new type for argv, so that we can make it `Send`
62+
struct Argv(Vec<*const c_char>);
63+
64+
// It is safe to make Argv Send, because it contains pointers to memory owned by `Command.args`
65+
unsafe impl Send for Argv {}
66+
6167
// passed back to std::process with the pipes connected to the child, if any
6268
// were requested
6369
pub struct StdioPipes {
@@ -87,17 +93,12 @@ pub enum Stdio {
8793
Fd(FileDesc),
8894
}
8995

90-
// Command is not Send by default due to the Command.argv field containing a raw pointers. However
91-
// it is safe to implement Send, because anyway, these pointers point to memory owned by the
92-
// Command.args field.
93-
unsafe impl Send for Command {}
94-
9596
impl Command {
9697
pub fn new(program: &OsStr) -> Command {
9798
let mut saw_nul = false;
9899
let program = os2c(program, &mut saw_nul);
99100
Command {
100-
argv: vec![program.as_ptr(), ptr::null()],
101+
argv: Argv(vec![program.as_ptr(), ptr::null()]),
101102
program,
102103
args: Vec::new(),
103104
env: Default::default(),
@@ -116,8 +117,8 @@ impl Command {
116117
// Overwrite the trailing NULL pointer in `argv` and then add a new null
117118
// pointer.
118119
let arg = os2c(arg, &mut self.saw_nul);
119-
self.argv[self.args.len() + 1] = arg.as_ptr();
120-
self.argv.push(ptr::null());
120+
self.argv.0[self.args.len() + 1] = arg.as_ptr();
121+
self.argv.0.push(ptr::null());
121122

122123
// Also make sure we keep track of the owned value to schedule a
123124
// destructor for this memory.
@@ -138,7 +139,7 @@ impl Command {
138139
self.saw_nul
139140
}
140141
pub fn get_argv(&self) -> &Vec<*const c_char> {
141-
&self.argv
142+
&self.argv.0
142143
}
143144

144145
#[allow(dead_code)]

0 commit comments

Comments
 (0)