about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-07-25 23:11:10 -0700
committerBrian Anderson <banderson@mozilla.com>2011-07-26 11:12:20 -0700
commite37dd2646a4808fff5647bc8d1a45914cd157c53 (patch)
tree50db2dd293e22ec83ce8d02fe5ecfa755e24e579
parentf110c206097e9483cbe68be50eca80ac63abcbbd (diff)
downloadrust-e37dd2646a4808fff5647bc8d1a45914cd157c53.tar.gz
rust-e37dd2646a4808fff5647bc8d1a45914cd157c53.zip
Clone all data before before putting it in a test closure
Putting shared boxes into a closure then running that closure in parallel
tasks seems like a recipe for refcounting disaster.

This doesn't completely fix the problems when running in parallel, but I'm
working on it.
-rw-r--r--src/test/compiletest/compiletest.rs36
1 files changed, 33 insertions, 3 deletions
diff --git a/src/test/compiletest/compiletest.rs b/src/test/compiletest/compiletest.rs
index 2bca022eeb4..b424b4bf605 100644
--- a/src/test/compiletest/compiletest.rs
+++ b/src/test/compiletest/compiletest.rs
@@ -207,9 +207,39 @@ iter iter_header(&str testfile) -> str {
 }
 
 fn make_test_fn(&cx cx, &str testfile) -> test::test_fn {
-    auto testcx = rec(config = cx.config,
-                      procsrv = procsrv::clone(cx.procsrv));
-    bind run_test(testcx, testfile)
+    // We're doing some ferociously unsafe nonsense here by creating a closure
+    // and letting the test runner spawn it into a task. To avoid having
+    // different tasks fighting over their refcounts and then the wrong task
+    // freeing a box we need to clone everything, and make sure our closure
+    // outlives all the tasks.
+    fn clonestr(&str s) -> str {
+        str::unsafe_from_bytes(str::bytes(s))
+    }
+
+    fn cloneoptstr(&option::t[str] s) -> option::t[str] {
+        alt s {
+          option::some(?s) { option::some(clonestr(s)) }
+          option::none { option::none }
+        }
+    }
+
+    auto configclone = rec(
+        compile_lib_path = clonestr(cx.config.compile_lib_path),
+        run_lib_path = clonestr(cx.config.run_lib_path),
+        rustc_path = clonestr(cx.config.rustc_path),
+        src_base = clonestr(cx.config.src_base),
+        build_base = clonestr(cx.config.build_base),
+        stage_id = clonestr(cx.config.stage_id),
+        mode = cx.config.mode,
+        run_ignored = cx.config.run_ignored,
+        filter = cloneoptstr(cx.config.filter),
+        runtool = cloneoptstr(cx.config.runtool),
+        rustcflags = cloneoptstr(cx.config.rustcflags),
+        verbose = cx.config.verbose);
+    auto cxclone = rec(config = configclone,
+                       procsrv = procsrv::clone(cx.procsrv));
+    auto testfileclone = clonestr(testfile);
+    ret bind run_test(cxclone, testfileclone);
 }
 
 fn run_test(cx cx, str testfile) {