Skip to content

Commit 83ca034

Browse files
committed
Merge remote-tracking branch 'brson/nocommupstream2'
2 parents 2372d2c + 1ef8394 commit 83ca034

25 files changed

+1683
-1184
lines changed

src/libcore/os.rs

+68-136
Original file line numberDiff line numberDiff line change
@@ -141,169 +141,101 @@ pub mod win32 {
141141
}
142142
}
143143

144-
pub fn getenv(n: &str) -> Option<~str> {
145-
global_env::getenv(n)
146-
}
144+
/*
145+
Accessing environment variables is not generally threadsafe.
146+
This uses a per-runtime lock to serialize access.
147+
XXX: It would probably be appropriate to make this a real global
148+
*/
149+
fn with_env_lock<T>(f: &fn() -> T) -> T {
150+
use private::global::global_data_clone_create;
151+
use private::{Exclusive, exclusive};
152+
153+
struct SharedValue(());
154+
type ValueMutex = Exclusive<SharedValue>;
155+
fn key(_: ValueMutex) { }
147156

148-
pub fn setenv(n: &str, v: &str) {
149-
global_env::setenv(n, v)
150-
}
157+
unsafe {
158+
let lock: ValueMutex = global_data_clone_create(key, || {
159+
~exclusive(SharedValue(()))
160+
});
151161

152-
pub fn env() -> ~[(~str,~str)] {
153-
global_env::env()
162+
lock.with_imm(|_| f() )
163+
}
154164
}
155165

156-
mod global_env {
157-
//! Internal module for serializing access to getenv/setenv
158-
use either;
159-
use libc;
160-
use oldcomm;
161-
use option::Option;
162-
use private;
163-
use str;
164-
use task;
165-
166+
pub fn env() -> ~[(~str,~str)] {
166167
extern mod rustrt {
167-
unsafe fn rust_global_env_chan_ptr() -> *libc::uintptr_t;
168-
}
169-
170-
enum Msg {
171-
MsgGetEnv(~str, oldcomm::Chan<Option<~str>>),
172-
MsgSetEnv(~str, ~str, oldcomm::Chan<()>),
173-
MsgEnv(oldcomm::Chan<~[(~str,~str)]>)
174-
}
175-
176-
pub fn getenv(n: &str) -> Option<~str> {
177-
let env_ch = get_global_env_chan();
178-
let po = oldcomm::Port();
179-
oldcomm::send(env_ch, MsgGetEnv(str::from_slice(n),
180-
oldcomm::Chan(&po)));
181-
oldcomm::recv(po)
182-
}
183-
184-
pub fn setenv(n: &str, v: &str) {
185-
let env_ch = get_global_env_chan();
186-
let po = oldcomm::Port();
187-
oldcomm::send(env_ch, MsgSetEnv(str::from_slice(n),
188-
str::from_slice(v),
189-
oldcomm::Chan(&po)));
190-
oldcomm::recv(po)
191-
}
192-
193-
pub fn env() -> ~[(~str,~str)] {
194-
let env_ch = get_global_env_chan();
195-
let po = oldcomm::Port();
196-
oldcomm::send(env_ch, MsgEnv(oldcomm::Chan(&po)));
197-
oldcomm::recv(po)
198-
}
199-
200-
fn get_global_env_chan() -> oldcomm::Chan<Msg> {
201-
unsafe {
202-
let global_ptr = rustrt::rust_global_env_chan_ptr();
203-
private::chan_from_global_ptr(global_ptr, || {
204-
// FIXME (#2621): This would be a good place to use a very
205-
// small foreign stack
206-
task::task().sched_mode(task::SingleThreaded).unlinked()
207-
}, global_env_task)
208-
}
168+
unsafe fn rust_env_pairs() -> ~[~str];
209169
}
210170

211-
fn global_env_task(msg_po: oldcomm::Port<Msg>) {
212-
unsafe {
213-
do private::weaken_task |weak_po| {
214-
loop {
215-
match oldcomm::select2(msg_po, weak_po) {
216-
either::Left(MsgGetEnv(ref n, resp_ch)) => {
217-
oldcomm::send(resp_ch, impl_::getenv(*n))
218-
}
219-
either::Left(MsgSetEnv(ref n, ref v, resp_ch)) => {
220-
oldcomm::send(resp_ch, impl_::setenv(*n, *v))
221-
}
222-
either::Left(MsgEnv(resp_ch)) => {
223-
oldcomm::send(resp_ch, impl_::env())
224-
}
225-
either::Right(_) => break
226-
}
227-
}
171+
unsafe {
172+
do with_env_lock {
173+
let mut pairs = ~[];
174+
for vec::each(rustrt::rust_env_pairs()) |p| {
175+
let vs = str::splitn_char(*p, '=', 1u);
176+
assert vec::len(vs) == 2u;
177+
pairs.push((copy vs[0], copy vs[1]));
228178
}
179+
move pairs
229180
}
230181
}
182+
}
231183

232-
mod impl_ {
233-
use cast;
234-
use libc;
235-
use option::Option;
236-
use option;
237-
use ptr;
238-
use str;
239-
use vec;
240-
241-
extern mod rustrt {
242-
unsafe fn rust_env_pairs() -> ~[~str];
243-
}
244-
245-
pub fn env() -> ~[(~str,~str)] {
246-
unsafe {
247-
let mut pairs = ~[];
248-
for vec::each(rustrt::rust_env_pairs()) |p| {
249-
let vs = str::splitn_char(*p, '=', 1u);
250-
assert vec::len(vs) == 2u;
251-
pairs.push((copy vs[0], copy vs[1]));
252-
}
253-
move pairs
254-
}
255-
}
256-
257-
#[cfg(unix)]
258-
pub fn getenv(n: &str) -> Option<~str> {
259-
unsafe {
260-
let s = str::as_c_str(n, |s| libc::getenv(s));
261-
return if ptr::null::<u8>() == cast::reinterpret_cast(&s) {
262-
option::None::<~str>
263-
} else {
264-
let s = cast::reinterpret_cast(&s);
265-
option::Some::<~str>(str::raw::from_buf(s))
266-
};
184+
#[cfg(unix)]
185+
pub fn getenv(n: &str) -> Option<~str> {
186+
unsafe {
187+
do with_env_lock {
188+
let s = str::as_c_str(n, |s| libc::getenv(s));
189+
if ptr::null::<u8>() == cast::reinterpret_cast(&s) {
190+
option::None::<~str>
191+
} else {
192+
let s = cast::reinterpret_cast(&s);
193+
option::Some::<~str>(str::raw::from_buf(s))
267194
}
268195
}
196+
}
197+
}
269198

270-
#[cfg(windows)]
271-
pub fn getenv(n: &str) -> Option<~str> {
272-
unsafe {
273-
use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
274-
do as_utf16_p(n) |u| {
275-
do fill_utf16_buf_and_decode() |buf, sz| {
276-
libc::GetEnvironmentVariableW(u, buf, sz)
277-
}
199+
#[cfg(windows)]
200+
pub fn getenv(n: &str) -> Option<~str> {
201+
unsafe {
202+
do with_env_lock {
203+
use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
204+
do as_utf16_p(n) |u| {
205+
do fill_utf16_buf_and_decode() |buf, sz| {
206+
libc::GetEnvironmentVariableW(u, buf, sz)
278207
}
279208
}
280209
}
210+
}
211+
}
281212

282213

283-
#[cfg(unix)]
284-
pub fn setenv(n: &str, v: &str) {
285-
unsafe {
286-
do str::as_c_str(n) |nbuf| {
287-
do str::as_c_str(v) |vbuf| {
288-
libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
289-
}
214+
#[cfg(unix)]
215+
pub fn setenv(n: &str, v: &str) {
216+
unsafe {
217+
do with_env_lock {
218+
do str::as_c_str(n) |nbuf| {
219+
do str::as_c_str(v) |vbuf| {
220+
libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
290221
}
291222
}
292223
}
224+
}
225+
}
293226

294227

295-
#[cfg(windows)]
296-
pub fn setenv(n: &str, v: &str) {
297-
unsafe {
298-
use os::win32::as_utf16_p;
299-
do as_utf16_p(n) |nbuf| {
300-
do as_utf16_p(v) |vbuf| {
301-
libc::SetEnvironmentVariableW(nbuf, vbuf);
302-
}
228+
#[cfg(windows)]
229+
pub fn setenv(n: &str, v: &str) {
230+
unsafe {
231+
do with_env_lock {
232+
use os::win32::as_utf16_p;
233+
do as_utf16_p(n) |nbuf| {
234+
do as_utf16_p(v) |vbuf| {
235+
libc::SetEnvironmentVariableW(nbuf, vbuf);
303236
}
304237
}
305238
}
306-
307239
}
308240
}
309241

src/libcore/pipes.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,16 @@ pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
12861286
(port, chan)
12871287
}
12881288

1289+
impl<T: Owned> PortOne<T> {
1290+
fn recv(self) -> T { recv_one(self) }
1291+
fn try_recv(self) -> Option<T> { try_recv_one(self) }
1292+
}
1293+
1294+
impl<T: Owned> ChanOne<T> {
1295+
fn send(self, data: T) { send_one(self, data) }
1296+
fn try_send(self, data: T) -> bool { try_send_one(self, data) }
1297+
}
1298+
12891299
/**
12901300
* Receive a message from a oneshot pipe, failing if the connection was
12911301
* closed.

0 commit comments

Comments
 (0)