From 2537ca318a65e29e085ed1f8e4f88387b21fdbad Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 14 May 2003 13:53:40 +0000 Subject: [PATCH] Add support for atexit handlers to the JIT, fixing 2003-05-14-AtExit.c llvm-svn: 6193 --- llvm/lib/ExecutionEngine/JIT/Intercept.cpp | 19 ++++++++++++++++--- llvm/lib/ExecutionEngine/JIT/JIT.cpp | 6 +++++- llvm/lib/ExecutionEngine/JIT/VM.h | 7 +++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/llvm/lib/ExecutionEngine/JIT/Intercept.cpp b/llvm/lib/ExecutionEngine/JIT/Intercept.cpp index 448ff2d3563c..aa58186ad859 100644 --- a/llvm/lib/ExecutionEngine/JIT/Intercept.cpp +++ b/llvm/lib/ExecutionEngine/JIT/Intercept.cpp @@ -12,6 +12,17 @@ #include // dlsym access #include +// AtExitList - List of functions registered with the at_exit function +static std::vector AtExitList; + +void VM::runAtExitHandlers() { + while (!AtExitList.empty()) { + void (*Fn)() = AtExitList.back(); + AtExitList.pop_back(); + Fn(); + } +} + //===----------------------------------------------------------------------===// // Function stubs that are invoked instead of raw system calls //===----------------------------------------------------------------------===// @@ -21,12 +32,14 @@ static void NoopFn() {} // jit_exit - Used to intercept the "exit" system call. static void jit_exit(int Status) { - exit(Status); // Do nothing for now. + VM::runAtExitHandlers(); // Run at_exit handlers... + exit(Status); } // jit_atexit - Used to intercept the "at_exit" system call. static int jit_atexit(void (*Fn)(void)) { - return atexit(Fn); // Do nothing for now. + AtExitList.push_back(Fn); // Take note of at_exit handler... + return 0; // Always successful } //===----------------------------------------------------------------------===// @@ -38,7 +51,7 @@ static int jit_atexit(void (*Fn)(void)) { void *VM::getPointerToNamedFunction(const std::string &Name) { // Check to see if this is one of the functions we want to intercept... if (Name == "exit") return (void*)&jit_exit; - if (Name == "at_exit") return (void*)&jit_atexit; + if (Name == "atexit") return (void*)&jit_atexit; // If it's an external function, look it up in the process image... void *Ptr = dlsym(0, Name.c_str()); diff --git a/llvm/lib/ExecutionEngine/JIT/JIT.cpp b/llvm/lib/ExecutionEngine/JIT/JIT.cpp index 39f305e12700..05aa934a85c3 100644 --- a/llvm/lib/ExecutionEngine/JIT/JIT.cpp +++ b/llvm/lib/ExecutionEngine/JIT/JIT.cpp @@ -50,5 +50,9 @@ int VM::run(const std::string &FnName, const std::vector &Args) { char **Argv = (char**)CreateArgv(Args); // Call the main function... - return PF(Args.size(), Argv); + int Result = PF(Args.size(), Argv); + + // Run any atexit handlers now! + runAtExitHandlers(); + return Result; } diff --git a/llvm/lib/ExecutionEngine/JIT/VM.h b/llvm/lib/ExecutionEngine/JIT/VM.h index 17c4ddd3dce8..a720c960f3dd 100644 --- a/llvm/lib/ExecutionEngine/JIT/VM.h +++ b/llvm/lib/ExecutionEngine/JIT/VM.h @@ -27,6 +27,7 @@ class VM : public ExecutionEngine { // handler to lazily patch up references... // std::map FunctionRefs; + public: VM(Module *M, TargetMachine *tm); ~VM(); @@ -54,6 +55,12 @@ public: // which causes lazy compilation of the target function. // static void CompilationCallback(); + + /// runAtExitHandlers - Before exiting the program, at_exit functions must be + /// called. This method calls them. + /// + static void runAtExitHandlers(); + private: static MachineCodeEmitter *createEmitter(VM &V); void setupPassManager();