From a467e8e4e6981208b0de4e5fb44885f12c390412 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 19 Jul 2011 23:33:37 -0700 Subject: [PATCH] Add a huge hack to allow the test runner to continue if a single task leaks This is just until unwinding works. Adds a flag to the runtime to turn the memory leak checks on task destruction into warnings instead of fatal errors. I am so sorry. Issue #428 --- src/lib/test.rs | 14 ++++++++++++++ src/rt/memory_region.cpp | 13 ++++++++++++- src/rt/memory_region.h | 5 +++++ src/rt/rust_builtin.cpp | 7 +++++++ src/rt/rustrt.def.in | 1 + 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/lib/test.rs b/src/lib/test.rs index ab88d16c38fd..d39385cbb5c3 100644 --- a/src/lib/test.rs +++ b/src/lib/test.rs @@ -227,12 +227,26 @@ fn run_test(&test_desc test) -> test_result { } } +native "rust" mod rustrt { + fn hack_allow_leaks(); +} + // We need to run our tests in another task in order to trap test failures. // But, at least currently, functions can't be used as spawn arguments so // we've got to treat our test functions as unsafe pointers. fn run_test_fn_in_task(&fn() f) -> bool { fn run_task(*mutable fn() fptr) { + // If this task fails we don't want that failure to propagate to the + // test runner or else we couldn't keep running tests task::unsupervise(); + + // FIXME (236): Hack supreme - unwinding doesn't work yet so if this + // task fails memory will not be freed correctly. This turns off the + // sanity checks in the runtime's memory region for the task, so that + // the test runner can continue. + rustrt::hack_allow_leaks(); + + // Run the test (*fptr)() } auto fptr = ptr::addr_of(f); diff --git a/src/rt/memory_region.cpp b/src/rt/memory_region.cpp index 13de56a3361a..0d10146a52bc 100644 --- a/src/rt/memory_region.cpp +++ b/src/rt/memory_region.cpp @@ -152,10 +152,21 @@ memory_region::~memory_region() { } } #endif - _srv->fatal(msg, __FILE__, __LINE__, "%d objects", _live_allocations); + if (!_hack_allow_leaks) { + _srv->fatal(msg, __FILE__, __LINE__, + "%d objects", _live_allocations); + } else { + _srv->warning(msg, __FILE__, __LINE__, + "%d objects", _live_allocations); + } if (_synchronized) { _lock.unlock(); } } +void +memory_region::hack_allow_leaks() { + _hack_allow_leaks = true; +} + // // Local Variables: // mode: C++ diff --git a/src/rt/memory_region.h b/src/rt/memory_region.h index 4c95d392ee60..7f19893b73ae 100644 --- a/src/rt/memory_region.h +++ b/src/rt/memory_region.h @@ -22,6 +22,7 @@ private: const bool _detailed_leaks; const bool _synchronized; lock_and_signal _lock; + bool _hack_allow_leaks; void add_alloc(); void dec_alloc(); @@ -33,6 +34,10 @@ public: void *realloc(void *mem, size_t size); void free(void *mem); virtual ~memory_region(); + // FIXME (236: This is a temporary hack to allow failing tasks that leak + // to not kill the entire process, which the test runner needs. Please + // kill with prejudice once unwinding works. + void hack_allow_leaks(); }; inline void *operator new(size_t size, memory_region ®ion) { diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index e434138f102c..f35a7a2e2cf4 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -459,6 +459,13 @@ debug_opaque(rust_task *task, type_desc *t, uint8_t *front) } } +extern "C" CDECL void +hack_allow_leaks(rust_task *task) +{ + LOG(task, stdlib, "hack_allow_leaks"); + task->local_region.hack_allow_leaks(); +} + struct rust_box { RUST_REFCOUNTED(rust_box) diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index f762f4a9be3c..f5b6e8c01eff 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -10,6 +10,7 @@ debug_trap debug_tydesc do_gc get_time +hack_allow_leaks ivec_copy_from_buf ivec_copy_from_buf_shared ivec_on_heap