On Sun, 2020-03-29 at 21:31 +0100, Andrea Corallo wrote: > David Malcolm <dmalc...@redhat.com> writes: > > > On Wed, 2020-03-18 at 23:51 +0100, Andrea Corallo wrote: > > Please add the new test to the header in its alphabetical location, > > i.e. between: > > > > /* test-vector-types.cc: We don't use this, since it's C++. */ > > > > and > > > > /* test-volatile.c */ > > > > An entry also needs to be added to the "testcases" array at the end > > of > > the header (again, in the alphabetical-sorted location). > > I tried adding the test into the "testcases" array but this makes the > threads test failing. > > I think this has nothing to do with this patch and happen just > because > this test does not define any code. Infact I see the same happening > just adding "test-empty.c" to the "testcases" array on the current > master. > > The error is not very reproducible, I tried a run under valgrind but > have found nothing so far :/ > > Dave do you recall if there was a specific reason not to have > "test-empty.c" into the "testcases" array? > > Andrea
It's a double-free bug in lra.c, albeit one that requires being used in a multithreaded way from libgccjit to be triggered. libgccjit's test-threads.c repeatedly compiles and runs numerous tests, each in a separate thread. Attempting to add an empty test that generates no code leads to a double-free ICE within that thread, within lra.c's finish_insn_code_data_once. The root cause is that the insn_code_data array is cleared in init_insn_code_data_once, but this is only called the first time a cgraph_node is expanded [1], whereas the "loop-over-all-elements and free them" is unconditionally called in finalize [2]. Hence if there are no functions: * the array is not re-initialized for the empty context * when finish_insn_code_data_once is called for the empty context it still contains the freed pointers from the previous context that held the jit mutex, and hence the free is a double-free. This patch sets the pointers to NULL after freeing them, fixing the ICE. The calls to free are still guarded by a check for NULL, which is redundant, but maybe there's a reason for not wanting to call "free" on a possibly-NULL value many times on process exit? (it makes the diff cleaner, at least) Fixes the issue in jit.dg. Full bootstrap & regression test in progress. Is it OK for master if it passes? Thanks Dave [1] init_insn_code_data_once is called via lra_init_once called by ira_init_once called by initialize_rtl, via: if (!rtl_initialized) ira_init_once (); called by init_function_start called by cgraph_node::expand [2]: finish_insn_code_data_once is called by: lra_finish_once called by finalize gcc/ChangeLog: * lra.c (finish_insn_code_data_once): Set the array elements to NULL after freeing them. gcc/testsuite/ChangeLog: * jit.dg/all-non-failing-tests.h: Add test-empty.c --- gcc/lra.c | 5 ++++- gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/gcc/lra.c b/gcc/lra.c index d5ea3622686..5e8b75b1fda 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -653,7 +653,10 @@ finish_insn_code_data_once (void) for (unsigned int i = 0; i < NUM_INSN_CODES; i++) { if (insn_code_data[i] != NULL) - free (insn_code_data[i]); + { + free (insn_code_data[i]); + insn_code_data[i] = NULL; + } } } diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index b2acc74ae95..af744192a73 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -116,6 +116,13 @@ #undef create_code #undef verify_code +/* test-empty.c */ +#define create_code create_code_empty +#define verify_code verify_code_empty +#include "test-empty.c" +#undef create_code +#undef verify_code + /* test-error-*.c: We don't use these test cases, since they deliberately introduce errors, which we don't want here. */ @@ -328,6 +335,9 @@ const struct testcase testcases[] = { {"expressions", create_code_expressions, verify_code_expressions}, + {"empty", + create_code_empty, + verify_code_empty}, {"factorial", create_code_factorial, verify_code_factorial}, -- 2.21.0