[LLVMdev] "Recursive compilation detected" and signals

Matt Renzelmann mjr at cs.wisc.edu
Tue Jul 14 15:31:01 PDT 2009


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




More information about the llvm-dev mailing list