CrashHandlerImpl() { // Install exception handler only if we don't have Google breakpad // All this old code can be removed completly later on. #ifdef NBREAKPAD setSignalHandlers(); DumpCallstack(NullOut()); // dummy call to force loading dynamic lib at this point (with sane heap) for backtrace and friends notes << "registered simple signal handler" << endl; #endif }
CrashHandlerImpl() { if(CrashHandler_RecoverAfterCrash) { setSignalHandlers(); DumpCallstack(NullOut); // dummy call to force loading dynamic lib at this point (with sane heap) for backtrace and friends notes << "registered simple resuming signal handler" << endl; } else notes << "no signal handler with these settings" << endl; }
static void SimpleSignalHandler(int signr, siginfo_t *info, void *secret) { signal(signr, SIG_IGN); // discard all remaining signals signal_def *d = NULL; for (unsigned int i = 0; i < sizeof(signal_data) / sizeof(signal_def); i++) if (signr == signal_data[i].id) { d = &signal_data[i]; break; } if (d) printf("Got signal 0x%02X (%s): %s\n", signr, d->name, d->description); else printf("Got signal 0x%02X\n", signr); /* see this article for further details: (thanks also for some code snippets) http://www.linuxjournal.com/article/6391 */ void *pnt = NULL; #if defined(__APPLE__) # if defined(__x86_64__) ucontext_t* uc = (ucontext_t*) secret; pnt = (void*) uc->uc_mcontext->__ss.__rip ; # elif defined(__hppa__) ucontext_t* uc = (ucontext_t*) secret; pnt = (void*) uc->uc_mcontext.sc_iaoq[0] & ~0x3UL ; # elif (defined (__ppc__)) || (defined (__powerpc__)) ucontext_t* uc = (ucontext_t*) secret; # if __DARWIN_UNIX03 pnt = (void*) uc->uc_mcontext->__ss.__srr0 ; # else pnt = (void*) uc->uc_mcontext->ss.srr0 ; # endif # elif defined(__sparc__) struct sigcontext* sc = (struct sigcontext*) secret; # if __WORDSIZE == 64 pnt = (void*) scp->sigc_regs.tpc ; # else pnt = (void*) scp->si_regs.pc ; # endif # elif defined(__i386__) ucontext_t* uc = (ucontext_t*) secret; # if __DARWIN_UNIX03 pnt = (void*) uc->uc_mcontext->__ss.__eip ; # else pnt = (void*) uc->uc_mcontext->ss.eip ; # endif # else # warning mcontext is not defined for this arch, thus a dumped backtrace could be crippled # endif #elif defined(__linux__) # if defined(__x86_64__) ucontext_t* uc = (ucontext_t*) secret; pnt = (void*) uc->uc_mcontext.gregs[REG_RIP] ; # elif defined(__hppa__) ucontext_t* uc = (ucontext_t*) secret; pnt = (void*) uc->uc_mcontext.sc_iaoq[0] & ~0x3UL ; # elif (defined (__ppc__)) || (defined (__powerpc__)) ucontext_t* uc = (ucontext_t*) secret; pnt = (void*) uc->uc_mcontext.regs->nip ; # elif defined(__sparc__) struct sigcontext* sc = (struct sigcontext*) secret; # if __WORDSIZE == 64 pnt = (void*) scp->sigc_regs.tpc ; # else pnt = (void*) scp->si_regs.pc ; # endif # elif defined(__i386__) ucontext_t* uc = (ucontext_t*) secret; pnt = (void*) uc->uc_mcontext.gregs[REG_EIP] ; # else # warning mcontext is not defined for this arch, thus a dumped backtrace could be crippled # endif #else # warning mcontest is not defined for this system, thus a dumped backtraced could be crippled #endif /* potentially correct for other archs: * alpha: ucp->m_context.sc_pc * arm: ucp->m_context.ctx.arm_pc * ia64: ucp->m_context.sc_ip & ~0x3UL * mips: ucp->m_context.sc_pc * s390: ucp->m_context.sregs->regs.psw.addr */ if (signr == SIGSEGV || signr == SIGBUS) printf("Faulty address is %p, called from %p\n", info->si_addr, pnt); /* The first two entries in the stack frame chain when you * get into the signal handler contain, respectively, a * return address inside your signal handler and one inside * sigaction() in libc. The stack frame of the last function * called before the signal (which, in case of fault signals, * also is the one that supposedly caused the problem) is lost. */ /* the third parameter to the signal handler points to an * ucontext_t structure that contains the values of the CPU * registers when the signal was raised. */ // WARNING: dont use cout here in this function, it sometimes screws the cout up // look at signal(2) for a list of safe functions DumpCallstackPrintf(pnt); #ifdef DEBUG // commented out for now because it still doesn't work that good //OlxWriteCoreDump(d ? d->name : NULL); #endif if(!recoverAfterCrash) { fflush(stdout); abort(); #ifdef DEBUG // raise(SIGQUIT); #else // exit(-1); #endif return; } setSignalHandlers(); // reset handler printf("resuming ...\n"); fflush(stdout); setSignalHandlers(); siglongjmp(longJumpBuffer, 1); // jump back to main loop, maybe we'll be able to continue somehow }
void enable() { if(tLXOptions->bRecoverAfterCrash) setSignalHandlers(); }
int main( int argc, char *argv[] ) { signal( SIGPIPE, SIG_IGN ); std::string pipeFile = "/var/run/SomeUniqueName.sock"; std::string pidFile;// = "/var/run/SocketForwarder.pid"; int port = -1; bool isVerbose = false; bool foregroundDaemon = false; openlog( "socket_protector", LOG_PID | LOG_NOWAIT | LOG_CONS | LOG_PERROR, LOG_DAEMON ); std::vector<std::string> subCommand; for ( int a = 1; a < argc; ++a ) { std::string curarg = argv[a]; if ( curarg == "-v" || curarg == "-verbose" || curarg == "--verbose" ) isVerbose = true; else if ( curarg == "-f" || curarg == "-foreground" || curarg == "--foreground" ) foregroundDaemon = true; else if ( curarg == "-?" || curarg == "-h" || curarg == "-help" || curarg == "--help" ) { usageAndExit( argv[0], NULL, 0 ); } else if ( curarg == "-pid-file" || curarg == "--pid-file" ) { ++a; if ( a == argc ) usageAndExit( argv[0], "Invalid arguments", -1 ); pidFile = argv[a]; } else if ( curarg == "--" ) { for ( ++a; a < argc; ++a ) subCommand.push_back( std::string( argv[a] ) ); if ( subCommand.empty() ) usageAndExit( argv[0], "Missing sub-daemon arguments", -1 ); if ( subCommand[0][0] != '/' ) { // if stuff isn't in the execution path, like a relative // path, execvp will fail. Expand it out to a full path subCommand[0] = fixPath( subCommand[0] ); } break; } else if ( curarg[0] == '-' ) { usageAndExit( argv[0], "Unknown command line argument", -1 ); } else if ( port == -1 ) { long tmp = strtol( curarg.data(), NULL, 10 ); if ( tmp <= 0 || tmp > 65535 ) usageAndExit( argv[0], "Invalid port specification", -1 ); port = static_cast<int>( tmp ); } else usageAndExit( argv[0], "Invalid arguments", -1 ); } if ( port == -1 ) { usageAndExit( argv[0], "Missing port argument", -1 ); } if ( port < 1024 && geteuid() != 0 ) { syslog( LOG_ERR, "Attempt to use privileged port can only be done running as root" ); return -1; } // We need to wait for our child process from the backgrounding // process to be up and running or it's hard to see what is // wrong. so set up a named semaphore to wait on that in the // main thread, although we only need to do that in the case where // we are going to detach std::auto_ptr<Semaphore> startup; std::auto_ptr<SocketServer> servPtr; try { if ( ! foregroundDaemon ) { std::stringstream name; name << "SocketProtector" << getpid(); startup.reset( new Semaphore( name.str() ) ); pid_t detpid = fork(); if ( detpid < 0 ) { syslog( LOG_CRIT, "Unable to fork detached process" ); } if ( detpid != 0 ) { // wait for child to become active startup->wait(); // child is up... // PARENT EXIT exit( 0 ); } // this is now the child process, become session leader to // truly detach pid_t sid = setsid(); if ( sid < 0 ) syslog( LOG_CRIT, "Unable to become session leader" ); Daemon::closeFileDescriptors(); } else { Daemon::closeFileDescriptors( 3 ); } // Daemonization causes all open files to be closed, so we have to // restart syslogging afterwards openlog( "safe_daemon", LOG_PID | LOG_NOWAIT | LOG_CONS | LOG_PERROR, LOG_DAEMON ); int p = LOG_INFO; if ( isVerbose ) p = LOG_DEBUG; ( void )setlogmask( LOG_UPTO( p ) ); PID pf( pidFile ); syslog( LOG_NOTICE, "pid %d starting...", getpid() ); setSignalHandlers(); servPtr.reset( new SocketServer( subCommand, static_cast<uint16_t>( port ) ) ); theSocketServer = servPtr.get(); // ok, we're at a point where we are going to run, so // let the parent process know so it can continue allowing us // to detach... if ( startup.get() != NULL ) { startup->post(); startup.reset(); } syslog( LOG_DEBUG, "socket server starting..." ); theSocketServer->run(); syslog( LOG_DEBUG, "shutdown requested..." ); servPtr.reset(); theSocketServer = NULL; } catch ( std::exception &e ) { syslog( LOG_CRIT, "Unhandled exception: %s", e.what() ); } catch ( ... ) { syslog( LOG_CRIT, "Unhandled unknown exception" ); } // failsafe in case we got an exception... if ( startup.get() != NULL ) startup->post(); return 0; }
void enable() { if(CrashHandler_RecoverAfterCrash) setSignalHandlers(); }