@@ -141,169 +141,101 @@ pub mod win32 {
141
141
}
142
142
}
143
143
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 ) { }
147
156
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
+ } ) ;
151
161
152
- pub fn env ( ) -> ~ [ ( ~ str , ~ str ) ] {
153
- global_env :: env ( )
162
+ lock . with_imm ( |_| f ( ) )
163
+ }
154
164
}
155
165
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 ) ] {
166
167
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 ] ;
209
169
}
210
170
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 ] ) ) ;
228
178
}
179
+ move pairs
229
180
}
230
181
}
182
+ }
231
183
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) )
267
194
}
268
195
}
196
+ }
197
+ }
269
198
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 )
278
207
}
279
208
}
280
209
}
210
+ }
211
+ }
281
212
282
213
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 ) ;
290
221
}
291
222
}
292
223
}
224
+ }
225
+ }
293
226
294
227
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 ) ;
303
236
}
304
237
}
305
238
}
306
-
307
239
}
308
240
}
309
241
0 commit comments