diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2013-09-16 08:50:49 +0400 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2013-09-17 01:46:55 +0400 |
commit | 87cad9093454ec6316c2a649b239ac65d280a3ec (patch) | |
tree | 8c9fd9686206525249e728d999164306207e62a0 | |
parent | 4a0d2d244f47a57fa9c97777330fe8c382e353e8 (diff) | |
download | bdwgc-87cad9093454ec6316c2a649b239ac65d280a3ec.tar.gz |
Fix race in GC_print_all_errors regarding GC_leaked
* reclaim.c (GC_add_leaked): Remove FIXME.
* reclaim.c (GC_print_all_errors): Declare n_leaked, leaked[] local
variables initialized from GC_[n_]leaked while holding the allocation
lock (reset GC_n_leaked and GC_leaked[] as well); add GC_ASSERT for
n_leaked; use [n_]leaked while printing leaked objects count and
pointers.
* reclaim.c (GC_print_all_errors): Acquire lock to reset
printing_errors.
-rw-r--r-- | reclaim.c | 21 |
1 files changed, 13 insertions, 8 deletions
@@ -57,7 +57,6 @@ GC_INLINE void GC_add_leaked(ptr_t leaked) # endif GC_have_errors = TRUE; - /* FIXME: Prevent adding an object while printing leaked ones. */ if (GC_n_leaked < MAX_LEAKED) { GC_leaked[GC_n_leaked++] = leaked; /* Make sure it's not reclaimed this cycle */ @@ -71,7 +70,8 @@ GC_INNER void GC_print_all_errors(void) { static GC_bool printing_errors = FALSE; GC_bool have_errors; - unsigned i; + unsigned i, n_leaked; + ptr_t leaked[MAX_LEAKED]; DCL_LOCK_STATE; LOCK(); @@ -81,6 +81,11 @@ GC_INNER void GC_print_all_errors(void) } have_errors = GC_have_errors; printing_errors = TRUE; + n_leaked = GC_n_leaked; + GC_ASSERT(n_leaked <= MAX_LEAKED); + BCOPY(GC_leaked, leaked, n_leaked * sizeof(ptr_t)); + GC_n_leaked = 0; + BZERO(GC_leaked, n_leaked * sizeof(ptr_t)); UNLOCK(); if (GC_debugging_started) { @@ -89,17 +94,15 @@ GC_INNER void GC_print_all_errors(void) have_errors = FALSE; } - if (GC_n_leaked > 0) { - GC_err_printf("Found %u leaked objects:\n", GC_n_leaked); + if (n_leaked > 0) { + GC_err_printf("Found %u leaked objects:\n", n_leaked); have_errors = TRUE; } - for (i = 0; i < GC_n_leaked; ++i) { - ptr_t p = GC_leaked[i]; + for (i = 0; i < n_leaked; i++) { + ptr_t p = leaked[i]; GC_print_heap_obj(p); GC_free(p); - GC_leaked[i] = 0; } - GC_n_leaked = 0; if (have_errors # ifndef GC_ABORT_ON_LEAK @@ -109,7 +112,9 @@ GC_INNER void GC_print_all_errors(void) ABORT("Leaked or smashed objects encountered"); } + LOCK(); printing_errors = FALSE; + UNLOCK(); } |