@@ -141,101 +141,169 @@ pub mod win32 {
141
141
}
142
142
}
143
143
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 ) { }
156
-
157
- unsafe {
158
- let lock: ValueMutex = global_data_clone_create ( key, || {
159
- ~exclusive ( SharedValue ( ( ) ) )
160
- } ) ;
144
+ pub fn getenv ( n : & str ) -> Option < ~str > {
145
+ global_env:: getenv ( n)
146
+ }
161
147
162
- lock . with_imm ( |_| f ( ) )
163
- }
148
+ pub fn setenv ( n : & str , v : & str ) {
149
+ global_env :: setenv ( n , v )
164
150
}
165
151
166
152
pub fn env ( ) -> ~[ ( ~str , ~str ) ] {
153
+ global_env:: env ( )
154
+ }
155
+
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
+
167
166
extern mod rustrt {
168
- unsafe fn rust_env_pairs ( ) -> ~ [ ~ str ] ;
167
+ unsafe fn rust_global_env_chan_ptr ( ) -> * libc :: uintptr_t ;
169
168
}
170
169
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 ] ) ) ;
178
- }
179
- move pairs
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)
180
208
}
181
209
}
182
- }
183
210
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) )
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
+ }
194
228
}
195
229
}
196
230
}
197
- }
198
231
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)
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 ] ) ) ;
207
252
}
253
+ move pairs
208
254
}
209
255
}
210
- }
211
- }
212
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
+ } ;
267
+ }
268
+ }
213
269
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 ) ;
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
+ }
221
278
}
222
279
}
223
280
}
224
- }
225
- }
226
281
227
282
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) ;
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
+ }
236
290
}
237
291
}
238
292
}
293
+
294
+
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
+ }
303
+ }
304
+ }
305
+ }
306
+
239
307
}
240
308
}
241
309
0 commit comments