ca7d7a6ad69056034c50055a4baa31466c1f04e4
galt
  Wed Jun 26 17:35:06 2013 -0700
fixing dumpstack to use _exit instead of exit so that the child cleanup will not close the mysql connections that are shared with the parent process.
diff --git src/lib/osunix.c src/lib/osunix.c
index 63bf87a..7bb2bd7 100644
--- src/lib/osunix.c
+++ src/lib/osunix.c
@@ -552,45 +552,66 @@
 attr.c_lflag = old;
 if (tcsetattr(STDIN_FILENO, TCSANOW, &attr) == -1)
     errAbort("Couldn't do tcsetattr2");
 return c;
 }
 
 boolean isPipe(int fd)
 /* determine in an open file is a pipe  */
 {
 struct stat buf;
 if (fstat(fd, &buf) < 0)
     errnoAbort("isPipe: fstat failed");
 return S_ISFIFO(buf.st_mode);
 }
 
+void childExecFailedExit(char *msg)
+/* Child exec failed, so quit without atexit cleanup */
+{
+fprintf(stderr, "child exec failed: %s\n", msg);
+fflush(stderr);
+_exit(1);  // Let the parent know that the child failed by returning 1.
+
+/* Explanation:
+_exit() is not the normal exit().  
+_exit() avoids the usual atexit() cleanup.
+The MySQL library that we link to uses atexit() cleanup to close any open MySql connections.
+However, because the child's mysql connections are shared by the parent,
+this causes the parent MySQL connections to become invalid,
+and causes the puzzling "MySQL has gone away" error in the parent
+when it tries to use its now invalid MySQL connections.
+*/
+
+}
+
 static void execPStack(pid_t ppid)
 /* exec pstack on the specified pid */
 {
 char *cmd[3], pidStr[32];
 safef(pidStr, sizeof(pidStr), "%ld", (long)ppid);
 cmd[0] = "pstack";
 cmd[1] = pidStr;
 cmd[2] = NULL;
 
 // redirect stdout to stderr
 if (dup2(2, 1) < 0)
     errAbort("dup2 failed");
 
 execvp(cmd[0], cmd);
-errAbort("exec failed: %s", cmd[0]);
+
+childExecFailedExit(cmd[0]); // cannot use the normal errAbort.
+
 }
 
 void vaDumpStack(char *format, va_list args)
 /* debugging function to run the pstack program on the current process. In
  * prints a message, following by a new line, and then the stack track.  Just
  * prints errors to stderr rather than aborts. For debugging purposes
  * only.  */
 {
 static boolean inDumpStack = FALSE;  // don't allow re-entry if called from error handler
 if (inDumpStack)
     return;
 inDumpStack = TRUE;
 
 fflush(stdout);  // clear buffer before forking
 vfprintf(stderr, format, args);