@@ -139,169 +139,101 @@ pub mod win32 {
139
139
}
140
140
}
141
141
142
- pub fn getenv ( n : & str ) -> Option < ~str > {
143
- global_env:: getenv ( n)
144
- }
142
+ /*
143
+ Accessing environment variables is not generally threadsafe.
144
+ This uses a per-runtime lock to serialize access.
145
+ XXX: It would probably be appropriate to make this a real global
146
+ */
147
+ fn with_env_lock < T > ( f : & fn ( ) -> T ) -> T {
148
+ use private:: global:: global_data_clone_create;
149
+ use private:: { Exclusive , exclusive} ;
150
+
151
+ struct SharedValue ( ( ) ) ;
152
+ type ValueMutex = Exclusive < SharedValue > ;
153
+ fn key ( _: ValueMutex ) { }
145
154
146
- pub fn setenv ( n : & str , v : & str ) {
147
- global_env:: setenv ( n, v)
148
- }
155
+ unsafe {
156
+ let lock: ValueMutex = global_data_clone_create ( key, || {
157
+ ~exclusive ( SharedValue ( ( ) ) )
158
+ } ) ;
149
159
150
- pub fn env ( ) -> ~ [ ( ~ str , ~ str ) ] {
151
- global_env :: env ( )
160
+ lock . with_imm ( |_| f ( ) )
161
+ }
152
162
}
153
163
154
- mod global_env {
155
- //! Internal module for serializing access to getenv/setenv
156
- use either;
157
- use libc;
158
- use oldcomm;
159
- use option:: Option ;
160
- use private;
161
- use str;
162
- use task;
163
-
164
+ pub fn env ( ) -> ~[ ( ~str , ~str ) ] {
164
165
extern mod rustrt {
165
- unsafe fn rust_global_env_chan_ptr ( ) -> * libc:: uintptr_t ;
166
- }
167
-
168
- enum Msg {
169
- MsgGetEnv ( ~str , oldcomm:: Chan < Option < ~str > > ) ,
170
- MsgSetEnv ( ~str , ~str , oldcomm:: Chan < ( ) > ) ,
171
- MsgEnv ( oldcomm:: Chan < ~[ ( ~str , ~str ) ] > )
172
- }
173
-
174
- pub fn getenv ( n : & str ) -> Option < ~str > {
175
- let env_ch = get_global_env_chan ( ) ;
176
- let po = oldcomm:: Port ( ) ;
177
- oldcomm:: send ( env_ch, MsgGetEnv ( str:: from_slice ( n) ,
178
- oldcomm:: Chan ( & po) ) ) ;
179
- oldcomm:: recv ( po)
180
- }
181
-
182
- pub fn setenv ( n : & str , v : & str ) {
183
- let env_ch = get_global_env_chan ( ) ;
184
- let po = oldcomm:: Port ( ) ;
185
- oldcomm:: send ( env_ch, MsgSetEnv ( str:: from_slice ( n) ,
186
- str:: from_slice ( v) ,
187
- oldcomm:: Chan ( & po) ) ) ;
188
- oldcomm:: recv ( po)
166
+ unsafe fn rust_env_pairs ( ) -> ~[ ~str ] ;
189
167
}
190
168
191
- pub fn env ( ) -> ~[ ( ~str , ~str ) ] {
192
- let env_ch = get_global_env_chan ( ) ;
193
- let po = oldcomm:: Port ( ) ;
194
- oldcomm:: send ( env_ch, MsgEnv ( oldcomm:: Chan ( & po) ) ) ;
195
- oldcomm:: recv ( po)
196
- }
197
-
198
- fn get_global_env_chan ( ) -> oldcomm:: Chan < Msg > {
199
- unsafe {
200
- let global_ptr = rustrt:: rust_global_env_chan_ptr ( ) ;
201
- private:: chan_from_global_ptr ( global_ptr, || {
202
- // FIXME (#2621): This would be a good place to use a very
203
- // small foreign stack
204
- task:: task ( ) . sched_mode ( task:: SingleThreaded ) . unlinked ( )
205
- } , global_env_task)
206
- }
207
- }
208
-
209
- fn global_env_task ( msg_po : oldcomm:: Port < Msg > ) {
210
- unsafe {
211
- do private:: weaken_task |weak_po| {
212
- loop {
213
- match oldcomm:: select2 ( msg_po, weak_po) {
214
- either:: Left ( MsgGetEnv ( ref n, resp_ch) ) => {
215
- oldcomm:: send ( resp_ch, impl_:: getenv ( * n) )
216
- }
217
- either:: Left ( MsgSetEnv ( ref n, ref v, resp_ch) ) => {
218
- oldcomm:: send ( resp_ch, impl_:: setenv ( * n, * v) )
219
- }
220
- either:: Left ( MsgEnv ( resp_ch) ) => {
221
- oldcomm:: send ( resp_ch, impl_:: env ( ) )
222
- }
223
- either:: Right ( _) => break
224
- }
225
- }
169
+ unsafe {
170
+ do with_env_lock {
171
+ let mut pairs = ~[ ] ;
172
+ for vec:: each( rustrt:: rust_env_pairs( ) ) |p| {
173
+ let vs = str:: splitn_char ( * p, '=' , 1 u) ;
174
+ assert vec:: len ( vs) == 2 u;
175
+ pairs. push ( ( copy vs[ 0 ] , copy vs[ 1 ] ) ) ;
226
176
}
177
+ move pairs
227
178
}
228
179
}
180
+ }
229
181
230
- mod impl_ {
231
- use cast;
232
- use libc;
233
- use option:: Option ;
234
- use option;
235
- use ptr;
236
- use str;
237
- use vec;
238
-
239
- extern mod rustrt {
240
- unsafe fn rust_env_pairs ( ) -> ~[ ~str ] ;
241
- }
242
-
243
- pub fn env ( ) -> ~[ ( ~str , ~str ) ] {
244
- unsafe {
245
- let mut pairs = ~[ ] ;
246
- for vec:: each( rustrt:: rust_env_pairs( ) ) |p| {
247
- let vs = str:: splitn_char ( * p, '=' , 1 u) ;
248
- assert vec:: len ( vs) == 2 u;
249
- pairs. push ( ( copy vs[ 0 ] , copy vs[ 1 ] ) ) ;
250
- }
251
- move pairs
252
- }
253
- }
254
-
255
- #[ cfg( unix) ]
256
- pub fn getenv ( n : & str ) -> Option < ~str > {
257
- unsafe {
258
- let s = str:: as_c_str ( n, |s| libc:: getenv ( s) ) ;
259
- return if ptr:: null :: < u8 > ( ) == cast:: reinterpret_cast ( & s) {
260
- option:: None :: < ~str >
261
- } else {
262
- let s = cast:: reinterpret_cast ( & s) ;
263
- option:: Some :: < ~str > ( str:: raw:: from_buf ( s) )
264
- } ;
182
+ #[ cfg( unix) ]
183
+ pub fn getenv ( n : & str ) -> Option < ~str > {
184
+ unsafe {
185
+ do with_env_lock {
186
+ let s = str:: as_c_str ( n, |s| libc:: getenv ( s) ) ;
187
+ if ptr:: null :: < u8 > ( ) == cast:: reinterpret_cast ( & s) {
188
+ option:: None :: < ~str >
189
+ } else {
190
+ let s = cast:: reinterpret_cast ( & s) ;
191
+ option:: Some :: < ~str > ( str:: raw:: from_buf ( s) )
265
192
}
266
193
}
194
+ }
195
+ }
267
196
268
- #[ cfg( windows) ]
269
- pub fn getenv ( n : & str ) -> Option < ~str > {
270
- unsafe {
271
- use os :: win32 :: { as_utf16_p , fill_utf16_buf_and_decode } ;
272
- do as_utf16_p( n ) |u| {
273
- do fill_utf16_buf_and_decode ( ) |buf , sz | {
274
- libc :: GetEnvironmentVariableW ( u , buf, sz)
275
- }
197
+ #[ cfg( windows) ]
198
+ pub fn getenv ( n : & str ) -> Option < ~str > {
199
+ unsafe {
200
+ do with_env_lock {
201
+ use os :: win32 : : { as_utf16_p, fill_utf16_buf_and_decode } ;
202
+ do as_utf16_p ( n ) |u | {
203
+ do fill_utf16_buf_and_decode ( ) | buf, sz| {
204
+ libc :: GetEnvironmentVariableW ( u , buf , sz )
276
205
}
277
206
}
278
207
}
208
+ }
209
+ }
279
210
280
211
281
- #[ cfg( unix) ]
282
- pub fn setenv ( n : & str , v : & str ) {
283
- unsafe {
284
- do str :: as_c_str ( n ) |nbuf| {
285
- do str:: as_c_str ( v ) |vbuf | {
286
- libc :: funcs :: posix01 :: unistd :: setenv ( nbuf , vbuf, 1 ) ;
287
- }
212
+ #[ cfg( unix) ]
213
+ pub fn setenv ( n : & str , v : & str ) {
214
+ unsafe {
215
+ do with_env_lock {
216
+ do str:: as_c_str ( n ) |nbuf | {
217
+ do str :: as_c_str ( v ) | vbuf| {
218
+ libc :: funcs :: posix01 :: unistd :: setenv ( nbuf , vbuf , 1 ) ;
288
219
}
289
220
}
290
221
}
222
+ }
223
+ }
291
224
292
225
293
- #[ cfg( windows) ]
294
- pub fn setenv ( n : & str , v : & str ) {
295
- unsafe {
296
- use os :: win32 :: as_utf16_p ;
297
- do as_utf16_p( n ) |nbuf| {
298
- do as_utf16_p ( v ) |vbuf | {
299
- libc :: SetEnvironmentVariableW ( nbuf , vbuf) ;
300
- }
226
+ #[ cfg( windows) ]
227
+ pub fn setenv ( n : & str , v : & str ) {
228
+ unsafe {
229
+ do with_env_lock {
230
+ use os :: win32 :: as_utf16_p;
231
+ do as_utf16_p ( n ) |nbuf | {
232
+ do as_utf16_p ( v ) | vbuf| {
233
+ libc :: SetEnvironmentVariableW ( nbuf , vbuf ) ;
301
234
}
302
235
}
303
236
}
304
-
305
237
}
306
238
}
307
239
0 commit comments