示例#1
0
	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;
	}
示例#3
0
	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
	}
示例#4
0
	void enable() { if(tLXOptions->bRecoverAfterCrash) setSignalHandlers(); }
示例#5
0
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(); }