@@ -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, '=' , 1 u) ;
176+ assert vec:: len ( vs) == 2 u;
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, '=' , 1 u) ;
250- assert vec:: len ( vs) == 2 u;
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
0 commit comments