For PR495:
[oota-llvm.git] / lib / Debugger / UnixLocalInferiorProcess.cpp
index ff9a15a1ead60bec2cd3fea06797012c79065e42..1731beaa0396f742539500d8132bed224fec3170 100644 (file)
@@ -1,18 +1,18 @@
 //===-- UnixLocalInferiorProcess.cpp - A Local process on a Unixy system --===//
-// 
+//
 //                     The LLVM Compiler Infrastructure
 //
 // This file was developed by the LLVM research group and is distributed under
 // the University of Illinois Open Source License. See LICENSE.TXT for details.
-// 
+//
 //===----------------------------------------------------------------------===//
-// 
+//
 // This file provides one implementation of the InferiorProcess class, which is
 // designed to be used on unixy systems (those that support pipe, fork, exec,
 // and signals).
 //
 // When the process is started, the debugger creates a pair of pipes, forks, and
-// makes the child starts executing the program.  The child executes the process
+// makes the child start executing the program.  The child executes the process
 // with an IntrinsicLowering instance that turns debugger intrinsics into actual
 // callbacks.
 //
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Debugger/InferiorProcess.h"
-#include "llvm/IntrinsicLowering.h"
 #include "llvm/Constant.h"
+#include "llvm/Instructions.h"
 #include "llvm/Module.h"
 #include "llvm/ModuleProvider.h"
 #include "llvm/Type.h"
-#include "llvm/iOther.h"
+#include "llvm/CodeGen/IntrinsicLowering.h"
 #include "llvm/ExecutionEngine/GenericValue.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "Support/FileUtilities.h"
-#include "Support/StringExtras.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/ADT/StringExtras.h"
+#include "FDHandle.h"
 #include <cerrno>
-#include <unistd.h>        // Unix specific debugger support
+#include <csignal>
+#include <unistd.h>        // Unix-specific debugger support
 #include <sys/types.h>
 #include <sys/wait.h>
 using namespace llvm;
@@ -55,7 +57,7 @@ static void runChild(Module *M, const std::vector<std::string> &Arguments,
 // enters a message processing loop, where it reads and responds to commands
 // until the parent decides that it wants to continue execution in some way.
 //
-// Whenever the child process stops, it notifies the debugger by sending an
+// Whenever the child process stops, it notifies the debugger by sending a
 // character over the wire.
 //
 
@@ -92,7 +94,7 @@ namespace {
 
     // FinishProgram: FrameDesc*->char - This command causes the program to
     // continue execution until the specified function frame returns.
-    FinishProgram, 
+    FinishProgram,
 
     // ContProgram: void->char - This command causes the program to continue
     // execution, stopping at some point in the future.
@@ -215,7 +217,7 @@ IP::IP(Module *M, const std::vector<std::string> &Arguments,
 
   // Start the child running...
   startChild(M, Arguments, envp);
-  
+
   // Okay, we created the program and it is off and running.  Wait for it to
   // stop now.
   try {
@@ -323,7 +325,7 @@ const GlobalVariable *IP::getSubprogramDesc(void *Frame) const {
 
 /// getFrameLocation - This method returns the source location where each stack
 /// frame is stopped.
-void IP::getFrameLocation(void *Frame, unsigned &LineNo, unsigned &ColNo, 
+void IP::getFrameLocation(void *Frame, unsigned &LineNo, unsigned &ColNo,
                           const GlobalVariable *&SourceDesc) const {
   sendCommand(GetFrameLocation, &Frame, sizeof(Frame));
   LocationToken Loc;
@@ -417,7 +419,10 @@ void IP::writeToChild(void *Buffer, unsigned Size) const {
 /// died, otherwise it just returns the exit code if it had to be killed.
 void IP::killChild() const {
   assert(ChildPID != 0 && "Child has already been reaped!");
-  
+
+  // If the process terminated on its own accord, closing the pipe file
+  // descriptors, we will get here.  Check to see if the process has already
+  // died in this manner, gracefully.
   int Status = 0;
   int PID;
   do {
@@ -425,7 +430,23 @@ void IP::killChild() const {
   } while (PID < 0 && errno == EINTR);
   if (PID < 0) throw "Error waiting for child to exit!";
 
-  // If the child process was already dead, then it died unexpectedly.
+  // Ok, there is a slight race condition here.  It's possible that we will find
+  // out that the file descriptor closed before waitpid will indicate that the
+  // process gracefully died.  If we don't know that the process gracefully
+  // died, wait a bit and try again.  This is pretty nasty.
+  if (PID == 0) {
+    usleep(10000);   // Wait a bit.
+
+    // Try again.
+    Status = 0;
+    do {
+      PID = waitpid(ChildPID, &Status, WNOHANG);
+    } while (PID < 0 && errno == EINTR);
+    if (PID < 0) throw "Error waiting for child to exit!";
+  }
+
+  // If the child process was already dead, then indicate that the process
+  // terminated on its own.
   if (PID) {
     assert(PID == ChildPID && "Didn't reap child?");
     ChildPID = 0;            // Child has been reaped
@@ -435,7 +456,7 @@ void IP::killChild() const {
       throw InferiorProcessDead(WTERMSIG(Status));
     throw InferiorProcessDead(-1);
   }
-  
+
   // Otherwise, the child exists and has not yet been killed.
   if (kill(ChildPID, SIGKILL) < 0)
     throw "Error killing child process!";
@@ -569,6 +590,7 @@ namespace {
 
     /// writeToParent - Send the specified buffer of data to the debugger
     /// process.
+    ///
     void writeToParent(const void *Buffer, unsigned Size);
 
     /// readFromParent - Read the specified number of bytes from the parent.
@@ -584,6 +606,7 @@ namespace {
 
     /// startSubprogram - This method creates a new region for the subroutine
     /// with the specified descriptor.
+    ///
     void startSubprogram(void *FuncDesc);
 
     /// startRegion - This method initiates the creation of an anonymous region.
@@ -597,6 +620,7 @@ namespace {
     /// reachedLine - This method is automatically called by the program every
     /// time it executes an llvm.dbg.stoppoint intrinsic.  If the debugger wants
     /// us to stop here, we do so, otherwise we continue execution.
+    ///
     void reachedLine(unsigned Line, unsigned Col, void *SourceDesc);
   };
 
@@ -852,12 +876,12 @@ namespace {
         break;
 
       case Intrinsic::dbg_region_end:
-        // Turn call into a call to llvm_debugger_stop
+        // Turn call into a call to llvm_dbg_region_end
         CI->setOperand(0, M->getOrInsertFunction("llvm_dbg_region_end",
                                   CI->getCalledFunction()->getFunctionType()));
         break;
       case Intrinsic::dbg_func_start:
-        // Turn call into a call to llvm_debugger_stop
+        // Turn call into a call to llvm_dbg_subprogram
         CI->setOperand(0, M->getOrInsertFunction("llvm_dbg_subprogram",
                                   CI->getCalledFunction()->getFunctionType()));
         break;
@@ -881,7 +905,7 @@ static void runChild(Module *M, const std::vector<std::string> &Arguments,
     ExecutionEngine::create(new ExistingModuleProvider(M), false,
                             new DebuggerIntrinsicLowering());
   assert(EE && "Couldn't create an ExecutionEngine, not even an interpreter?");
-  
+
   // Call the main function from M as if its signature were:
   //   int main (int argc, char **argv, const char **envp)
   // using the contents of Args to determine argc & argv, and the contents of