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);