Matt Renzelmann
2009-Jul-14 22:31 UTC
[LLVMdev] "Recursive compilation detected" and signals
Hello, Platform is RHEL5, GCC 4.2.4, x86-32, and LLVM/LLVM-GCC from subversion (yesterday evening). I'm compiling C code into bitcode, and then executing the bitcode using the JIT compiler (lli). I've managed to reproduce a problem when multiple signals go off around the same time. A sample program is below. The result is the "recursive compilation detected" JIT compiler error. The same program compiled via GCC works fine. Note that the sample program uses the preprocessor to create large amounts of superfluous code to tie-up the JIT compiler. If you have an extremely fast CPU, try decreasing the timeout from 250ms. ====================================#include <stdio.h> #include <signal.h> #include <sys/time.h> #include <string.h> #define LEVEL1 { int x = rand(); printf ("", x); } #define LEVEL2 LEVEL1 LEVEL1 #define LEVEL3 LEVEL2 LEVEL2 #define LEVEL4 LEVEL3 LEVEL3 #define LEVEL5 LEVEL4 LEVEL4 #define LEVEL6 LEVEL5 LEVEL5 #define LEVEL7 LEVEL6 LEVEL6 #define LEVEL8 LEVEL7 LEVEL7 #define LEVEL9 LEVEL8 LEVEL8 #define LEVEL10 LEVEL9 LEVEL9 #define LEVEL11 LEVEL10 LEVEL10 #define LEVEL12 LEVEL11 LEVEL11 #define LEVEL13 LEVEL12 LEVEL12 #define LEVEL14 LEVEL13 LEVEL13 #define LEVEL15 LEVEL14 LEVEL14 void timer_handler (int signum) { printf ("timer expired\n"); LEVEL13; } void sigsegv_handler (int signum) { printf ("Uh oh\n"); LEVEL13; } int main (int argc, char **argv) { struct itimerval timer; struct sigaction sa1, sa2; /* Configure the timer to expire after 250 msec... */ timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 250000; /* ... and every 250 msec after that. */ timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = 250000; /* Install timer_handler as the signal handler for SIGVTALRM. */ memset ((void *) &sa1, 0, (size_t) sizeof (sa1)); sa1.sa_handler = &timer_handler; sigaction (SIGVTALRM, &sa1, NULL); /* Install the SIGSEGV handler */ memset ((void *) &sa2, 0, (size_t) sizeof (sa2)); sa2.sa_handler = &sigsegv_handler; sigaction (SIGSEGV, &sa2, NULL); /* Set the timer to go off shortly */ if (setitimer(ITIMER_VIRTUAL, &timer, NULL) == -1) printf ("Failure!\n"); /* Send the SIGSEGV signal. This initiates JIT compilation of sigsegv_handler */ kill (getpid (), SIGSEGV); /* When the timer finally fires, assuming sigsegv_handler is still compiling, LLVM crashes */ for (;;); return 0; } ==================================== Compile the above program with: llvm-gcc -c -emit-llvm ./main.c -o main.bc And run it with: lli main.bc Here's the output from the debug version of the lli utility. Note that I slightly tweaked my version of LLVM to print out the function that it's attempting to JIT, and the function that it was previously JIT'ing when it detected the recursion. This print statement makes it clear that the JIT compiler was working on sigsegv_handler before it attempted to start on timer_handler. ====================================Recursive compilation: Function: timer_handler, existing function sigsegv_handler lli: JIT.cpp:579: void llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, const llvm::MutexGuard&): Assertion `!isAlreadyCodeGenerating && "Error: Recursive compilation detected!"' failed. 0 lli 0x08a5308e 1 lli 0x08a53601 2 0x008e0420 __kernel_sigreturn + 0 3 libc.so.6 0x00146ac1 abort + 257 4 libc.so.6 0x0013e39e __assert_fail + 238 5 lli 0x08738aa4 llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, llvm::MutexGuard const&) + 408 6 lli 0x08738f6d llvm::JIT::getPointerToFunction(llvm::Function*) + 755 7 lli 0x0873f704 8 lli 0x08597416 X86CompilationCallback2 + 166 9 lli 0x08596e08 X86CompilationCallback + 24 10 lli 0x00eebff5 X86CompilationCallback + 4170535429 11 lli 0x0863e13e llvm::CallSDNode::CallSDNode(unsigned int, llvm::DebugLoc, bool, bool, bool, llvm::SDVTList, llvm::SDValue const*, unsigned int, unsigned int) + 90 12 lli 0x08622d47 llvm::SelectionDAG::getCall(unsigned int, llvm::DebugLoc, bool, bool, bool, llvm::SDVTList, llvm::SDValue const*, unsigned int, unsigned int) + 419 13 lli 0x08648853 llvm::TargetLowering::LowerCallTo(llvm::SDValue, llvm::Type const*, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::SDValue, std::vector<llvm::TargetLowering::ArgListEntry, std::allocator<llvm::TargetLowering::ArgListEntry> >&, llvm::SelectionDAG&, llvm::DebugLoc) + 2125 14 lli 0x0864f8c6 llvm::SelectionDAGLowering::LowerCallTo(llvm::CallSite, llvm::SDValue, bool, llvm::MachineBasicBlock*) + 1418 15 lli 0x0865c6b1 llvm::SelectionDAGLowering::visitCall(llvm::CallInst&) + 2527 16 lli 0x08666d1e llvm::SelectionDAGLowering::visit(unsigned int, llvm::User&) + 1108 17 lli 0x08666e16 llvm::SelectionDAGLowering::visit(llvm::Instruction&) + 52 18 lli 0x086824ff llvm::SelectionDAGISel::SelectBasicBlock(llvm::BasicBlock*, llvm::ilist_iterator<llvm::Instruction>, llvm::ilist_iterator<llvm::Instruction>) + 99 19 lli 0x086830fd llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function&, llvm::MachineFunction&, llvm::MachineModuleInfo*, llvm::DwarfWriter*, llvm::TargetInstrInfo const&) + 2433 20 lli 0x08683f20 llvm::SelectionDAGISel::runOnFunction(llvm::Function&) + 908 21 lli 0x089dad71 llvm::FPPassManager::runOnFunction(llvm::Function&) + 289 22 lli 0x089db302 llvm::FunctionPassManagerImpl::run(llvm::Function&) + 124 23 lli 0x089db4d1 llvm::FunctionPassManager::run(llvm::Function&) + 135 24 lli 0x08738b09 llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, llvm::MutexGuard const&) + 509 25 lli 0x08738f6d llvm::JIT::getPointerToFunction(llvm::Function*) + 755 26 lli 0x0873f704 27 lli 0x08597416 X86CompilationCallback2 + 166 28 lli 0x08596e08 X86CompilationCallback + 24 29 lli 0x00eebfed X86CompilationCallback + 4170535421 30 lli 0x08759bdd llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::vector<std::string, std::allocator<std::string> > const&, char const* const*) + 1255 31 lli 0x08390e66 main + 1946 32 libc.so.6 0x001316d0 __libc_start_main + 224 33 lli 0x0838fd61 Stack dump: 0. Program arguments: /scratch/sym/llvm-current/Debug/bin/lli main.bc 1. Running pass 'X86 DAG->DAG Instruction Selection' on function '@sigsegv_handler' Aborted ==================================== I did a search in bugzilla, but it seems to responding very slowly at the moment, so I thought I'd post here first. Please let me know if I'm missing something :) Is this behavior by design or is it a bug/limitation? Thanks and regards, Matt