mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-11 06:24:24 +00:00
core: Convert getenv/setenv to use a mutex
This much simpler implementation uses a global mutex and eliminates the kernel environment channel.
This commit is contained in:
parent
8852279a9e
commit
fb9299346a
@ -139,169 +139,101 @@ pub mod win32 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
global_env::getenv(n)
|
||||
}
|
||||
/*
|
||||
Accessing environment variables is not generally threadsafe.
|
||||
This uses a per-runtime lock to serialize access.
|
||||
XXX: It would probably be appropriate to make this a real global
|
||||
*/
|
||||
fn with_env_lock<T>(f: &fn() -> T) -> T {
|
||||
use private::global::global_data_clone_create;
|
||||
use private::{Exclusive, exclusive};
|
||||
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
global_env::setenv(n, v)
|
||||
struct SharedValue(());
|
||||
type ValueMutex = Exclusive<SharedValue>;
|
||||
fn key(_: ValueMutex) { }
|
||||
|
||||
unsafe {
|
||||
let lock: ValueMutex = global_data_clone_create(key, || {
|
||||
~exclusive(SharedValue(()))
|
||||
});
|
||||
|
||||
lock.with_imm(|_| f() )
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> ~[(~str,~str)] {
|
||||
global_env::env()
|
||||
extern mod rustrt {
|
||||
unsafe fn rust_env_pairs() -> ~[~str];
|
||||
}
|
||||
|
||||
unsafe {
|
||||
do with_env_lock {
|
||||
let mut pairs = ~[];
|
||||
for vec::each(rustrt::rust_env_pairs()) |p| {
|
||||
let vs = str::splitn_char(*p, '=', 1u);
|
||||
assert vec::len(vs) == 2u;
|
||||
pairs.push((copy vs[0], copy vs[1]));
|
||||
}
|
||||
move pairs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod global_env {
|
||||
//! Internal module for serializing access to getenv/setenv
|
||||
use either;
|
||||
use libc;
|
||||
use oldcomm;
|
||||
use option::Option;
|
||||
use private;
|
||||
use str;
|
||||
use task;
|
||||
|
||||
extern mod rustrt {
|
||||
unsafe fn rust_global_env_chan_ptr() -> *libc::uintptr_t;
|
||||
}
|
||||
|
||||
enum Msg {
|
||||
MsgGetEnv(~str, oldcomm::Chan<Option<~str>>),
|
||||
MsgSetEnv(~str, ~str, oldcomm::Chan<()>),
|
||||
MsgEnv(oldcomm::Chan<~[(~str,~str)]>)
|
||||
}
|
||||
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
let env_ch = get_global_env_chan();
|
||||
let po = oldcomm::Port();
|
||||
oldcomm::send(env_ch, MsgGetEnv(str::from_slice(n),
|
||||
oldcomm::Chan(&po)));
|
||||
oldcomm::recv(po)
|
||||
}
|
||||
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
let env_ch = get_global_env_chan();
|
||||
let po = oldcomm::Port();
|
||||
oldcomm::send(env_ch, MsgSetEnv(str::from_slice(n),
|
||||
str::from_slice(v),
|
||||
oldcomm::Chan(&po)));
|
||||
oldcomm::recv(po)
|
||||
}
|
||||
|
||||
pub fn env() -> ~[(~str,~str)] {
|
||||
let env_ch = get_global_env_chan();
|
||||
let po = oldcomm::Port();
|
||||
oldcomm::send(env_ch, MsgEnv(oldcomm::Chan(&po)));
|
||||
oldcomm::recv(po)
|
||||
}
|
||||
|
||||
fn get_global_env_chan() -> oldcomm::Chan<Msg> {
|
||||
unsafe {
|
||||
let global_ptr = rustrt::rust_global_env_chan_ptr();
|
||||
private::chan_from_global_ptr(global_ptr, || {
|
||||
// FIXME (#2621): This would be a good place to use a very
|
||||
// small foreign stack
|
||||
task::task().sched_mode(task::SingleThreaded).unlinked()
|
||||
}, global_env_task)
|
||||
#[cfg(unix)]
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
unsafe {
|
||||
do with_env_lock {
|
||||
let s = str::as_c_str(n, |s| libc::getenv(s));
|
||||
if ptr::null::<u8>() == cast::reinterpret_cast(&s) {
|
||||
option::None::<~str>
|
||||
} else {
|
||||
let s = cast::reinterpret_cast(&s);
|
||||
option::Some::<~str>(str::raw::from_buf(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn global_env_task(msg_po: oldcomm::Port<Msg>) {
|
||||
unsafe {
|
||||
do private::weaken_task |weak_po| {
|
||||
loop {
|
||||
match oldcomm::select2(msg_po, weak_po) {
|
||||
either::Left(MsgGetEnv(ref n, resp_ch)) => {
|
||||
oldcomm::send(resp_ch, impl_::getenv(*n))
|
||||
}
|
||||
either::Left(MsgSetEnv(ref n, ref v, resp_ch)) => {
|
||||
oldcomm::send(resp_ch, impl_::setenv(*n, *v))
|
||||
}
|
||||
either::Left(MsgEnv(resp_ch)) => {
|
||||
oldcomm::send(resp_ch, impl_::env())
|
||||
}
|
||||
either::Right(_) => break
|
||||
}
|
||||
#[cfg(windows)]
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
unsafe {
|
||||
do with_env_lock {
|
||||
use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
|
||||
do as_utf16_p(n) |u| {
|
||||
do fill_utf16_buf_and_decode() |buf, sz| {
|
||||
libc::GetEnvironmentVariableW(u, buf, sz)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_ {
|
||||
use cast;
|
||||
use libc;
|
||||
use option::Option;
|
||||
use option;
|
||||
use ptr;
|
||||
use str;
|
||||
use vec;
|
||||
|
||||
extern mod rustrt {
|
||||
unsafe fn rust_env_pairs() -> ~[~str];
|
||||
}
|
||||
|
||||
pub fn env() -> ~[(~str,~str)] {
|
||||
unsafe {
|
||||
let mut pairs = ~[];
|
||||
for vec::each(rustrt::rust_env_pairs()) |p| {
|
||||
let vs = str::splitn_char(*p, '=', 1u);
|
||||
assert vec::len(vs) == 2u;
|
||||
pairs.push((copy vs[0], copy vs[1]));
|
||||
}
|
||||
move pairs
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
unsafe {
|
||||
let s = str::as_c_str(n, |s| libc::getenv(s));
|
||||
return if ptr::null::<u8>() == cast::reinterpret_cast(&s) {
|
||||
option::None::<~str>
|
||||
} else {
|
||||
let s = cast::reinterpret_cast(&s);
|
||||
option::Some::<~str>(str::raw::from_buf(s))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
unsafe {
|
||||
use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
|
||||
do as_utf16_p(n) |u| {
|
||||
do fill_utf16_buf_and_decode() |buf, sz| {
|
||||
libc::GetEnvironmentVariableW(u, buf, sz)
|
||||
}
|
||||
#[cfg(unix)]
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
unsafe {
|
||||
do with_env_lock {
|
||||
do str::as_c_str(n) |nbuf| {
|
||||
do str::as_c_str(v) |vbuf| {
|
||||
libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
unsafe {
|
||||
do str::as_c_str(n) |nbuf| {
|
||||
do str::as_c_str(v) |vbuf| {
|
||||
libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
|
||||
}
|
||||
#[cfg(windows)]
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
unsafe {
|
||||
do with_env_lock {
|
||||
use os::win32::as_utf16_p;
|
||||
do as_utf16_p(n) |nbuf| {
|
||||
do as_utf16_p(v) |vbuf| {
|
||||
libc::SetEnvironmentVariableW(nbuf, vbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
unsafe {
|
||||
use os::win32::as_utf16_p;
|
||||
do as_utf16_p(n) |nbuf| {
|
||||
do as_utf16_p(v) |vbuf| {
|
||||
libc::SetEnvironmentVariableW(nbuf, vbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -870,12 +870,6 @@ rust_task_unweaken(rust_port_id chan) {
|
||||
task->kernel->unweaken_task(chan);
|
||||
}
|
||||
|
||||
extern "C" CDECL uintptr_t*
|
||||
rust_global_env_chan_ptr() {
|
||||
rust_task *task = rust_get_current_task();
|
||||
return task->kernel->get_global_env_chan();
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
rust_task_inhibit_kill(rust_task *task) {
|
||||
task->inhibit_kill();
|
||||
|
@ -35,7 +35,6 @@ rust_kernel::rust_kernel(rust_env *env) :
|
||||
osmain_driver(NULL),
|
||||
non_weak_tasks(0),
|
||||
global_loop_chan(0),
|
||||
global_env_chan(0),
|
||||
at_exit_runner(NULL),
|
||||
at_exit_started(false),
|
||||
env(env),
|
||||
|
@ -131,8 +131,6 @@ class rust_kernel {
|
||||
|
||||
// Used to communicate with the process-side, global libuv loop
|
||||
uintptr_t global_loop_chan;
|
||||
// Used to serialize access to getenv/setenv
|
||||
uintptr_t global_env_chan;
|
||||
|
||||
lock_and_signal at_exit_lock;
|
||||
spawn_fn at_exit_runner;
|
||||
@ -193,7 +191,6 @@ public:
|
||||
bool send_to_port(rust_port_id chan, void *sptr);
|
||||
|
||||
uintptr_t* get_global_loop() { return &global_loop_chan; }
|
||||
uintptr_t* get_global_env_chan() { return &global_env_chan; }
|
||||
|
||||
void register_exit_function(spawn_fn runner, fn_env_pair *f);
|
||||
};
|
||||
|
@ -174,7 +174,6 @@ rust_dbg_do_nothing
|
||||
rust_dbg_breakpoint
|
||||
rust_osmain_sched_id
|
||||
rust_compare_and_swap_ptr
|
||||
rust_global_env_chan_ptr
|
||||
rust_port_take
|
||||
rust_port_drop
|
||||
rust_port_task
|
||||
|
Loading…
Reference in New Issue
Block a user