diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2012-02-07 18:55:02 -0800 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-02-07 19:57:03 -0800 |
| commit | 93450abb4bf6a755b343ca459bbeff92540a7822 (patch) | |
| tree | ee49c759c04ab7efb83025b9ed6b04878711ea39 /src/libstd | |
| parent | 5131216fa6826509bb31672e5fde15b18eeff5d7 (diff) | |
| download | rust-93450abb4bf6a755b343ca459bbeff92540a7822.tar.gz rust-93450abb4bf6a755b343ca459bbeff92540a7822.zip | |
Make process-spawning take environments and working directories, remove procsrv task from compiletest.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/freebsd_os.rs | 2 | ||||
| -rw-r--r-- | src/libstd/generic_os.rs | 22 | ||||
| -rw-r--r-- | src/libstd/linux_os.rs | 2 | ||||
| -rw-r--r-- | src/libstd/macos_os.rs | 2 | ||||
| -rw-r--r-- | src/libstd/run_program.rs | 123 | ||||
| -rw-r--r-- | src/libstd/test.rs | 11 | ||||
| -rw-r--r-- | src/libstd/win32_os.rs | 1 |
7 files changed, 127 insertions, 36 deletions
diff --git a/src/libstd/freebsd_os.rs b/src/libstd/freebsd_os.rs index 315813c0848..d7ca27b550b 100644 --- a/src/libstd/freebsd_os.rs +++ b/src/libstd/freebsd_os.rs @@ -20,6 +20,7 @@ export target_os; export dylib_filename; export get_exe_path; export fsync_fd; +export rustrt; // FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult // by https://github.com/graydon/rust/issues#issue/268 @@ -116,6 +117,7 @@ fn waitpid(pid: pid_t) -> i32 { #[abi = "cdecl"] native mod rustrt { + fn rust_env_pairs() -> [str]; fn rust_getcwd() -> str; } diff --git a/src/libstd/generic_os.rs b/src/libstd/generic_os.rs index f41e83fa5fb..0f9f8a58410 100644 --- a/src/libstd/generic_os.rs +++ b/src/libstd/generic_os.rs @@ -11,21 +11,23 @@ import core::option; // Wow, this is an ugly way to write doc comments #[cfg(bogus)] -/* -Function: getenv - -Get the value of an environment variable -*/ +#[doc = "Get the value of an environment variable"] fn getenv(n: str) -> option<str> { } #[cfg(bogus)] -/* -Function: setenv - -Set the value of an environment variable -*/ +#[doc = "Set the value of an environment variable"] fn setenv(n: str, v: str) { } +fn env() -> [(str,str)] { + let pairs = []; + for p in os::rustrt::rust_env_pairs() { + let vs = str::split(p, '=' as u8); + assert vec::len(vs) == 2u; + pairs += [(vs[0], vs[1])]; + } + ret pairs; +} + #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] diff --git a/src/libstd/linux_os.rs b/src/libstd/linux_os.rs index 05722333df8..0231add3cd4 100644 --- a/src/libstd/linux_os.rs +++ b/src/libstd/linux_os.rs @@ -20,6 +20,7 @@ export target_os; export dylib_filename; export get_exe_path; export fsync_fd; +export rustrt; // FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult // by https://github.com/graydon/rust/issues#issue/268 @@ -112,6 +113,7 @@ fn waitpid(pid: pid_t) -> i32 { #[abi = "cdecl"] native mod rustrt { + fn rust_env_pairs() -> [str]; fn rust_getcwd() -> str; } diff --git a/src/libstd/macos_os.rs b/src/libstd/macos_os.rs index 920061cfd31..e44bc4c20e2 100644 --- a/src/libstd/macos_os.rs +++ b/src/libstd/macos_os.rs @@ -14,6 +14,7 @@ export target_os; export dylib_filename; export get_exe_path; export fsync_fd; +export rustrt; // FIXME Refactor into unix_os module or some such. Doesn't // seem to work right now. @@ -115,6 +116,7 @@ fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int { #[abi = "cdecl"] native mod rustrt { + fn rust_env_pairs() -> [str]; fn rust_getcwd() -> str; } diff --git a/src/libstd/run_program.rs b/src/libstd/run_program.rs index f81eda3aeeb..fa827c96f2f 100644 --- a/src/libstd/run_program.rs +++ b/src/libstd/run_program.rs @@ -5,7 +5,7 @@ Process spawning */ import option::{some, none}; import str::sbuf; -import ctypes::{fd_t, pid_t}; +import ctypes::{fd_t, pid_t, void}; export program; export run_program; @@ -16,8 +16,9 @@ export waitpid; #[abi = "cdecl"] native mod rustrt { - fn rust_run_program(argv: *sbuf, in_fd: fd_t, - out_fd: fd_t, err_fd: fd_t) -> pid_t; + fn rust_run_program(argv: *sbuf, envp: *void, dir: sbuf, + in_fd: fd_t, out_fd: fd_t, err_fd: fd_t) + -> pid_t; } /* Section: Types */ @@ -82,13 +83,6 @@ iface program { /* Section: Operations */ -fn arg_vec(prog: str, args: [@str]) -> [sbuf] { - let argptrs = str::as_buf(prog, {|buf| [buf] }); - for arg in args { argptrs += str::as_buf(*arg, {|buf| [buf] }); } - argptrs += [ptr::null()]; - ret argptrs; -} - /* Function: spawn_process @@ -98,6 +92,8 @@ Parameters: prog - The path to an executable args - Vector of arguments to pass to the child process +env - optional env-modification for child +dir - optional dir to run child in (default current dir) in_fd - A file descriptor for the child to use as std input out_fd - A file descriptor for the child to use as std output err_fd - A file descriptor for the child to use as std error @@ -106,18 +102,90 @@ Returns: The process id of the spawned process */ -fn spawn_process(prog: str, args: [str], in_fd: fd_t, - out_fd: fd_t, err_fd: fd_t) +fn spawn_process(prog: str, args: [str], + env: option<[(str,str)]>, + dir: option<str>, + in_fd: fd_t, out_fd: fd_t, err_fd: fd_t) -> pid_t unsafe { - // Note: we have to hold on to these vector references while we hold a - // pointer to their buffers - let prog = prog; - let args = vec::map(args, {|arg| @arg }); - let argv = arg_vec(prog, args); - let pid = - rustrt::rust_run_program(vec::unsafe::to_ptr(argv), in_fd, out_fd, - err_fd); - ret pid; + with_argv(prog, args) {|argv| + with_envp(env) { |envp| + with_dirp(dir) { |dirp| + rustrt::rust_run_program(argv, envp, dirp, + in_fd, out_fd, err_fd) + } + } + } +} + +fn with_argv<T>(prog: str, args: [str], + cb: fn(*sbuf) -> T) -> T unsafe { + let argptrs = str::as_buf(prog) {|b| [b] }; + let tmps = []; + for arg in args { + let t = @arg; + tmps += [t]; + argptrs += str::as_buf(*t) {|b| [b] }; + } + argptrs += [ptr::null()]; + vec::as_buf(argptrs, cb) +} + +#[cfg(target_os = "macos")] +#[cfg(target_os = "linux")] +#[cfg(target_os = "freebsd")] +fn with_envp<T>(env: option<[(str,str)]>, + cb: fn(*void) -> T) -> T unsafe { + // On posixy systems we can pass a char** for envp, which is + // a null-terminated array of "k=v\n" strings. + alt env { + some (es) { + let tmps = []; + let ptrs = []; + + for (k,v) in es { + let t = @(#fmt("%s=%s", k, v)); + vec::push(tmps, t); + ptrs += str::as_buf(*t) {|b| [b]}; + } + ptrs += [ptr::null()]; + vec::as_buf(ptrs) { |p| cb(::unsafe::reinterpret_cast(p)) } + } + none { + cb(ptr::null()) + } + } +} + +#[cfg(target_os = "win32")] +fn with_envp<T>(env: option<[(str,str)]>, + cb: fn(*void) -> T) -> T unsafe { + // On win32 we pass an "environment block" which is not a char**, but + // rather a concatenation of null-terminated k=v\0 sequences, with a final + // \0 to terminate. + alt env { + some (es) { + let blk : [u8] = []; + for (k,v) in es { + let t = #fmt("%s=%s", k, v); + let v : [u8] = ::unsafe::reinterpret_cast(t); + blk += v; + ::unsafe::leak(v); + } + blk += [0_u8]; + vec::as_buf(blk) {|p| cb(::unsafe::reinterpret_cast(p)) } + } + none { + cb(ptr::null()) + } + } +} + +fn with_dirp<T>(d: option<str>, + cb: fn(sbuf) -> T) -> T unsafe { + alt d { + some(dir) { str::as_buf(dir, cb) } + none { cb(ptr::null()) } + } } /* @@ -135,7 +203,8 @@ Returns: The process id */ fn run_program(prog: str, args: [str]) -> int { - ret waitpid(spawn_process(prog, args, 0i32, 0i32, 0i32)); + ret waitpid(spawn_process(prog, args, none, none, + 0i32, 0i32, 0i32)); } /* @@ -161,7 +230,8 @@ fn start_program(prog: str, args: [str]) -> program { let pipe_output = os::pipe(); let pipe_err = os::pipe(); let pid = - spawn_process(prog, args, pipe_input.in, pipe_output.out, + spawn_process(prog, args, none, none, + pipe_input.in, pipe_output.out, pipe_err.out); if pid == -1i32 { fail; } @@ -316,7 +386,8 @@ mod tests { let pid = run::spawn_process( - "cat", [], pipe_in.in, pipe_out.out, pipe_err.out); + "cat", [], none, none, + pipe_in.in, pipe_out.out, pipe_err.out); os::close(pipe_in.in); os::close(pipe_out.out); os::close(pipe_err.out); @@ -356,7 +427,9 @@ mod tests { #[test] fn waitpid() { - let pid = run::spawn_process("false", [], 0i32, 0i32, 0i32); + let pid = run::spawn_process("false", [], + none, none, + 0i32, 0i32, 0i32); let status = run::waitpid(pid); assert status == 1; } diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 6d7273ff0b1..8d5ecda2c48 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -227,10 +227,19 @@ fn run_tests(opts: test_opts, tests: [test_desc], } } +// Windows tends to dislike being overloaded with threads. +#[cfg(target_os = "win32")] +const sched_overcommit : uint = 1u; + +#[cfg(target_os = "linux")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "macos")] +const sched_overcommit : uint = 4u; + fn get_concurrency() -> uint { let threads = rustrt::sched_threads(); if threads == 1u { 1u } - else { threads * 4u } + else { threads * sched_overcommit } } fn filter_tests(opts: test_opts, diff --git a/src/libstd/win32_os.rs b/src/libstd/win32_os.rs index ddc1ebd7a35..aa589cf3c32 100644 --- a/src/libstd/win32_os.rs +++ b/src/libstd/win32_os.rs @@ -106,6 +106,7 @@ fn fsync_fd(_fd: fd_t, _level: io::fsync::level) -> c_int { #[abi = "cdecl"] native mod rustrt { + fn rust_env_pairs() -> [str]; fn rust_process_wait(handle: c_int) -> c_int; fn rust_getcwd() -> str; } |
