@@ -11,6 +11,7 @@ import std::generic_os::getenv;
11
11
import std:: os;
12
12
import std:: run;
13
13
import std:: task;
14
+ import std:: unsafe;
14
15
15
16
tag mode { mode_compile_fail; mode_run_fail; mode_run_pass; }
16
17
@@ -175,7 +176,6 @@ fn make_test(cx: &cx, testfile: &str, configport: &port[str]) ->
175
176
ignore: header:: is_test_ignored ( cx. config , testfile) }
176
177
}
177
178
178
-
179
179
/*
180
180
So this is kind of crappy:
181
181
@@ -223,7 +223,7 @@ fn closure_to_task(cx: cx, configport: port[str], testfn: &fn() ) -> task {
223
223
cx. config . run_ignored , opt_str ( cx. config . filter ) ,
224
224
opt_str ( cx. config . runtool ) ,
225
225
opt_str ( cx. config . rustcflags ) , cx. config . verbose ,
226
- procsrv :: clone ( cx. procsrv ) . chan , testfile) ;
226
+ task :: clone_chan ( cx. procsrv . chan ) , testfile) ;
227
227
}
228
228
229
229
fn run_test_task ( compile_lib_path : str , run_lib_path : str , rustc_path : str ,
@@ -304,6 +304,23 @@ fn logv(config: &config, s: &str) {
304
304
if config. verbose { io:: stdout ( ) . write_line ( s) ; }
305
305
}
306
306
307
+ fn clone_str ( s : & str ) -> str {
308
+ let new = s + "" ;
309
+ // new should be a different pointer
310
+ let sptr: int = unsafe :: reinterpret_cast ( s) ;
311
+ let newptr: int = unsafe :: reinterpret_cast ( new) ;
312
+ assert sptr != newptr;
313
+ new
314
+ }
315
+
316
+ fn clone_ivecstr ( v : & str [ ] ) -> str [ ] {
317
+ let r = ~[ ] ;
318
+ for t: str in ivec:: slice ( v, 0 u, ivec:: len ( v) ) {
319
+ r += ~[ clone_str ( t) ] ;
320
+ }
321
+ ret r;
322
+ }
323
+
307
324
mod header {
308
325
309
326
export test_props;
@@ -396,10 +413,10 @@ mod runtest {
396
413
log #fmt( "running %s" , testfile) ;
397
414
let props = load_props( testfile) ;
398
415
alt cx. config. mode {
399
- mode_compile_fail. { run_cfail_test( cx, props, testfile) ; }
400
- mode_run_fail. { run_rfail_test( cx, props, testfile) ; }
401
- mode_run_pass. { run_rpass_test( cx, props, testfile) ; }
402
- }
416
+ mode_compile_fail. { run_cfail_test( cx, props, testfile) ; }
417
+ mode_run_fail. { run_rfail_test( cx, props, testfile) ; }
418
+ mode_run_pass. { run_rpass_test( cx, props, testfile) ; }
419
+ }
403
420
}
404
421
405
422
fn run_cfail_test( cx: & cx, props: & test_props, testfile: & str ) {
@@ -622,7 +639,7 @@ mod procsrv {
622
639
623
640
type handle = { task: option:: t[ task] , chan: reqchan} ;
624
641
625
- tag request { exec( str , str , vec [ str ] , chan[ response] ) ; stop; }
642
+ tag request { exec( str , str , str [ ] , chan[ response] ) ; stop; }
626
643
627
644
type response = { pid: int, outfd: int, errfd: int} ;
628
645
@@ -631,7 +648,7 @@ mod procsrv {
631
648
let task = spawn fn ( setupchan: chan[ chan[ request] ] ) {
632
649
let reqport = port( ) ;
633
650
let reqchan = chan( reqport) ;
634
- task:: send( setupchan, reqchan) ;
651
+ task:: send( setupchan, task :: clone_chan ( reqchan) ) ;
635
652
worker( reqport) ;
636
653
} ( chan( setupport) ) ;
637
654
ret { task: option:: some( task) ,
@@ -657,7 +674,10 @@ mod procsrv {
657
674
{ status: int, out: str , err: str } {
658
675
let p = port[ response] ( ) ;
659
676
let ch = chan( p) ;
660
- task:: send( handle. chan, exec( lib_path, prog, args, ch) ) ;
677
+ task:: send( handle. chan, exec( lib_path,
678
+ prog,
679
+ clone_ivecstr( ivec:: from_vec( args) ) ,
680
+ task:: clone_chan( ch) ) ) ;
661
681
let resp = task:: recv( p) ;
662
682
let output = readclose( resp. outfd) ;
663
683
let errput = readclose( resp. errfd) ;
@@ -679,29 +699,64 @@ mod procsrv {
679
699
}
680
700
681
701
fn worker( p: port[ request] ) {
702
+
703
+ // FIXME: If we declare this inside of the while loop and then
704
+ // break out of it before it's ever initialized (i.e. we don't run
705
+ // any tests), then the cleanups will puke, so we're initializing it
706
+ // here with defaults.
707
+ let execparms = {
708
+ lib_path: "" ,
709
+ prog: "" ,
710
+ args: ~[ ] ,
711
+ // This works because a NULL box is ignored during cleanup
712
+ respchan: unsafe :: reinterpret_cast( 0 )
713
+ } ;
714
+
682
715
while true {
683
- alt task:: recv( p) {
684
- exec( lib_path, prog, args, respchan) {
685
- // This is copied from run::start_program
686
- let pipe_in = os:: pipe( ) ;
687
- let pipe_out = os:: pipe( ) ;
688
- let pipe_err = os:: pipe( ) ;
689
- let spawnproc =
690
- bind run:: spawn_process( prog, args, pipe_in. in,
691
- pipe_out. out, pipe_err. out) ;
692
- let pid = with_lib_path( lib_path, spawnproc) ;
693
- if pid == -1 { fail; }
694
- os:: libc:: close( pipe_in. in) ;
695
- os:: libc:: close( pipe_in. out) ;
696
- os:: libc:: close( pipe_out. out) ;
697
- os:: libc:: close( pipe_err. out) ;
698
- task:: send( respchan,
699
- { pid: pid,
700
- outfd: pipe_out. in,
701
- errfd: pipe_err. in} ) ;
702
- }
703
- stop. { ret; }
704
- }
716
+ // FIXME: Sending strings across channels seems to still
717
+ // leave them refed on the sender's end, which causes problems if
718
+ // the receiver's poniters outlive the sender's. Here we clone
719
+ // everything and let the originals go out of scope before sending
720
+ // a response.
721
+ execparms = {
722
+ // FIXME: The 'discriminant' of an alt expression has the
723
+ // same scope as the alt expression itself, so we have to put
724
+ // the entire alt in another block to make sure the exec
725
+ // message goes out of scope. Seems like the scoping rules for
726
+ // the alt discriminant are wrong.
727
+ alt task:: recv( p) {
728
+ exec( lib_path, prog, args, respchan) {
729
+ {
730
+ lib_path: clone_str( lib_path) ,
731
+ prog: clone_str( prog) ,
732
+ args: clone_ivecstr( args) ,
733
+ respchan: respchan
734
+ }
735
+ }
736
+ stop. { ret }
737
+ }
738
+ } ;
739
+
740
+ // This is copied from run::start_program
741
+ let pipe_in = os:: pipe( ) ;
742
+ let pipe_out = os:: pipe( ) ;
743
+ let pipe_err = os:: pipe( ) ;
744
+ let spawnproc =
745
+ bind run:: spawn_process( execparms. prog,
746
+ ivec:: to_vec( execparms. args) ,
747
+ pipe_in. in,
748
+ pipe_out. out,
749
+ pipe_err. out) ;
750
+ let pid = with_lib_path( execparms. lib_path, spawnproc) ;
751
+ if pid == -1 { fail; }
752
+ os:: libc:: close( pipe_in. in) ;
753
+ os:: libc:: close( pipe_in. out) ;
754
+ os:: libc:: close( pipe_out. out) ;
755
+ os:: libc:: close( pipe_err. out) ;
756
+ task:: send( execparms. respchan,
757
+ { pid: pid,
758
+ outfd: pipe_out. in,
759
+ errfd: pipe_err. in} ) ;
705
760
}
706
761
}
707
762
0 commit comments