@@ -265,11 +265,78 @@ the contents of stdout and the contents of stderr.
265
265
" ]
266
266
fn program_output ( prog : str , args : [ str ] ) ->
267
267
{ status : int , out : str , err : str } {
268
- let pr = start_program ( prog, args) ;
269
- pr. close_input ( ) ;
270
- let out = read_all ( pr. output ( ) ) ;
271
- let err = read_all ( pr. err ( ) ) ;
272
- ret { status : pr. finish ( ) , out : out, err : err} ;
268
+
269
+ let pipe_in = os:: pipe ( ) ;
270
+ let pipe_out = os:: pipe ( ) ;
271
+ let pipe_err = os:: pipe ( ) ;
272
+ let pid = spawn_process ( prog, args, none, none,
273
+ pipe_in. in , pipe_out. out , pipe_err. out ) ;
274
+
275
+ os:: close ( pipe_in. in ) ;
276
+ os:: close ( pipe_out. out ) ;
277
+ os:: close ( pipe_err. out ) ;
278
+ if pid == -1i32 {
279
+ os:: close ( pipe_in. out ) ;
280
+ os:: close ( pipe_out. in ) ;
281
+ os:: close ( pipe_err. in ) ;
282
+ fail;
283
+ }
284
+
285
+ os:: close ( pipe_in. out ) ;
286
+
287
+ // Spawn two entire schedulers to read both stdout and sterr
288
+ // in parallel so we don't deadlock while blocking on one
289
+ // or the other. FIXME: Surely there's a much more clever way
290
+ // to do this.
291
+ let p = comm:: port ( ) ;
292
+ let ch = comm:: chan ( p) ;
293
+ task:: spawn_sched ( task:: single_threaded) { ||
294
+ let errput = readclose ( pipe_err. in ) ;
295
+ comm:: send ( ch, ( 2 , errput) ) ;
296
+ } ;
297
+ task:: spawn_sched ( task:: single_threaded) { ||
298
+ let output = readclose ( pipe_out. in ) ;
299
+ comm:: send ( ch, ( 1 , output) ) ;
300
+ } ;
301
+ let status = run:: waitpid ( pid) ;
302
+ let mut errs = "" ;
303
+ let mut outs = "" ;
304
+ let mut count = 2 ;
305
+ while count > 0 {
306
+ let stream = comm:: recv ( p) ;
307
+ alt check stream {
308
+ ( 1 , s) {
309
+ outs = s;
310
+ }
311
+ ( 2 , s) {
312
+ errs = s;
313
+ }
314
+ } ;
315
+ count -= 1 ;
316
+ } ;
317
+ ret { status : status, out : outs, err : errs} ;
318
+ }
319
+
320
+ fn writeclose ( fd : c_int , s : str ) {
321
+ import io:: writer_util;
322
+
323
+ #error ( "writeclose %d, %s" , fd as int , s) ;
324
+ let writer = io:: fd_writer ( fd, false ) ;
325
+ writer. write_str ( s) ;
326
+
327
+ os:: close ( fd) ;
328
+ }
329
+
330
+ fn readclose ( fd : c_int ) -> str {
331
+ let file = os:: fdopen ( fd) ;
332
+ let reader = io:: FILE_reader ( file, false ) ;
333
+ let mut buf = "" ;
334
+ while !reader. eof ( ) {
335
+ let bytes = reader. read_bytes ( 4096 u) ;
336
+ buf += str:: from_bytes ( bytes) ;
337
+ }
338
+ os:: fclose ( file) ;
339
+ ret buf;
273
340
}
274
341
275
342
#[ doc ="Waits for a process to exit and returns the exit code" ]
@@ -351,27 +418,6 @@ mod tests {
351
418
log ( debug, expected) ;
352
419
log ( debug, actual) ;
353
420
assert ( expected == actual) ;
354
-
355
- fn writeclose ( fd : c_int , s : str ) {
356
- #error ( "writeclose %d, %s" , fd as int , s) ;
357
- let writer = io:: fd_writer ( fd, false ) ;
358
- writer. write_str ( s) ;
359
-
360
- os:: close ( fd) ;
361
- }
362
-
363
- fn readclose ( fd : c_int ) -> str {
364
- // Copied from run::program_output
365
- let file = os:: fdopen ( fd) ;
366
- let reader = io:: FILE_reader ( file, false ) ;
367
- let mut buf = "" ;
368
- while !reader. eof ( ) {
369
- let bytes = reader. read_bytes ( 4096 u) ;
370
- buf += str:: from_bytes ( bytes) ;
371
- }
372
- os:: fclose ( file) ;
373
- ret buf;
374
- }
375
421
}
376
422
377
423
#[ test]
0 commit comments