Improve error handling, output crashed thread name

This commit is contained in:
Glenn Maynard
2003-10-21 09:00:15 +00:00
parent 192d05a9c2
commit 06b6f2d6bc
2 changed files with 39 additions and 15 deletions
+28 -14
View File
@@ -105,6 +105,12 @@ static void parent_process( int to_child, void **BacktracePointers, int SignalRe
p = GetCheckpointLogs("\n"); p = GetCheckpointLogs("\n");
size = strlen(p)+1; size = strlen(p)+1;
parent_write(to_child, &size, sizeof(size)); parent_write(to_child, &size, sizeof(size));
parent_write(to_child, p, size);
/* 7. Write the crashed thread's name. */
p = RageThread::GetCurThreadName();
size = strlen(p)+1;
parent_write(to_child, &size, sizeof(size));
parent_write(to_child, p, size); parent_write(to_child, p, size);
close(to_child); close(to_child);
@@ -401,20 +407,30 @@ void CrashSignalHandler( int signal )
return; return;
#endif #endif
static bool received = false; static int received = 0;
static pid_t childpid = 0;
if( received ) if( received )
{ {
/* We've received a second signal. This may mean that another thread /* We've received a second signal. This may mean that another thread
* crashed before we stopped it, or it may mean that the crash handler * crashed before we stopped it, or it may mean that the crash handler
* crashed. */ * crashed. */
const char *str = "Oops! Fatal signal received while still in the crash handler\n"; const char *str;
write( fileno(stdout), str, strlen(str) ); fprintf(stderr, "got %i, in %i, %i %i\n", signal, getpid(), received, childpid);
if( received == getpid() )
str = "Oops! Fatal signal received while still in the crash handler\n";
else if( childpid == getpid() )
str = "Oops! Fatal signal received while in the crash handler child\n";
else
str = "Extra fatal signal received\n"; // probably another thread crashing
write( fileno(stderr), str, strlen(str) );
_exit(1); _exit(1);
} }
received = true; received = getpid();
RageThread::HaltAllThreads(); /* We want to stop other threads when crashing. However, sending SIGSTOPs is messy and
* tends to do more harm than good. Let's just try to get the crashdump written quickly. */
// RageThread::HaltAllThreads();
/* Do this early, so functions called below don't end up on the backtrace. */ /* Do this early, so functions called below don't end up on the backtrace. */
void *BacktracePointers[BACKTRACE_MAX_SIZE]; void *BacktracePointers[BACKTRACE_MAX_SIZE];
@@ -422,8 +438,6 @@ void CrashSignalHandler( int signal )
/* We need to be very careful, since we're under crash conditions. Let's fork /* We need to be very careful, since we're under crash conditions. Let's fork
* a process and exec ourself to get a clean environment to work in. */ * a process and exec ourself to get a clean environment to work in. */
//const char *my_fn = g_argv[0];
int fds[2]; int fds[2];
if(pipe(fds) != 0) if(pipe(fds) != 0)
{ {
@@ -431,14 +445,14 @@ void CrashSignalHandler( int signal )
exit(1); exit(1);
} }
pid_t pid = fork(); childpid = fork();
if(pid == -1) if( childpid == -1 )
{ {
safe_print(fileno(stderr), "Crash handler fork() failed: ", strerror(errno), "\n", NULL); safe_print(fileno(stderr), "Crash handler fork() failed: ", strerror(errno), "\n", NULL);
exit(1); exit(1);
} }
if(pid == 0) if( childpid == 0 )
{ {
close(fds[1]); close(fds[1]);
spawn_child_process(fds[0]); spawn_child_process(fds[0]);
@@ -447,10 +461,10 @@ void CrashSignalHandler( int signal )
{ {
close(fds[0]); close(fds[0]);
parent_process( fds[1], BacktracePointers, signal ); parent_process( fds[1], BacktracePointers, signal );
waitpid(pid, NULL, 0); int status = 0;
/* Now that we're done, actually kill all threads. kill(0) should kill ourself waitpid( childpid, &status, 0 );
* and all other threads. */ if( WIFSIGNALED(status) )
kill( 0, SIGKILL ); safe_print( fileno(stderr), "Crash handler child exited with signal ", itoa(WTERMSIG(status)), "\n", NULL);
} }
} }
@@ -377,6 +377,15 @@ static void child_process()
ret = read(3, temp, size); ret = read(3, temp, size);
CStringArray Checkpoints; CStringArray Checkpoints;
split(temp, "$$", Checkpoints); split(temp, "$$", Checkpoints);
delete [] temp;
/* 7. Read the crashed thread's name. */
ret = read(3, &size, sizeof(size));
temp = new char [size];
ret = read(3, temp, size);
const CString CrashedThread(temp);
printf("got '%s'\n", CrashedThread.c_str());
delete[] temp;
/* Wait for the child to either finish cleaning up or die. XXX: /* Wait for the child to either finish cleaning up or die. XXX:
* This should time out, in case something deadlocks. */ * This should time out, in case something deadlocks. */
@@ -448,7 +457,8 @@ static void child_process()
} }
#endif #endif
fprintf( CrashDump, "Crash reason: %s\n\n", Signal.c_str() ); fprintf( CrashDump, "Crash reason: %s\n", Signal.c_str() );
fprintf( CrashDump, "Crashed thread: %s\n\n", CrashedThread.c_str() );
fprintf(CrashDump, "Checkpoints:\n"); fprintf(CrashDump, "Checkpoints:\n");
for (unsigned i=0; i<Checkpoints.size(); ++i) for (unsigned i=0; i<Checkpoints.size(); ++i)