2006-04-05 20:20:46 +08:00
|
|
|
//
|
|
|
|
// ZoneMinder Signal Handling Implementation, $Date$, $Revision$
|
2008-07-25 17:33:23 +08:00
|
|
|
// Copyright (C) 2001-2008 Philip Coombes
|
2006-04-05 20:20:46 +08:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
|
|
|
// as published by the Free Software Foundation; either version 2
|
|
|
|
// of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "zm.h"
|
|
|
|
#include "zm_signal.h"
|
|
|
|
|
2011-06-21 17:19:10 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2013-10-06 23:26:33 +08:00
|
|
|
#define TRACE_SIZE 16
|
|
|
|
|
2006-04-05 20:20:46 +08:00
|
|
|
bool zm_reload = false;
|
2013-10-06 23:26:33 +08:00
|
|
|
bool zm_terminate = false;
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
RETSIGTYPE zm_hup_handler(int signal)
|
2006-04-05 20:20:46 +08:00
|
|
|
{
|
2008-07-23 03:54:01 +08:00
|
|
|
#if HAVE_STRSIGNAL
|
2013-10-07 07:57:01 +08:00
|
|
|
Info("Got signal %d (%s), reloading", signal, strsignal(signal));
|
|
|
|
#else // HAVE_STRSIGNAL
|
|
|
|
Info("Got HUP signal, reloading");
|
|
|
|
#endif // HAVE_STRSIGNAL
|
2006-04-05 20:20:46 +08:00
|
|
|
zm_reload = true;
|
|
|
|
}
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
RETSIGTYPE zm_term_handler(int signal)
|
2006-04-05 20:20:46 +08:00
|
|
|
{
|
2008-07-23 03:54:01 +08:00
|
|
|
#if HAVE_STRSIGNAL
|
2013-10-07 07:57:01 +08:00
|
|
|
Info("Got signal %d (%s), exiting", signal, strsignal(signal));
|
|
|
|
#else // HAVE_STRSIGNAL
|
|
|
|
Info("Got TERM signal, exiting");
|
|
|
|
#endif // HAVE_STRSIGNAL
|
2006-04-05 20:20:46 +08:00
|
|
|
zm_terminate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if HAVE_STRUCT_SIGCONTEXT
|
2013-10-07 07:57:01 +08:00
|
|
|
RETSIGTYPE zm_die_handler(int signal, struct sigcontext context)
|
2006-04-05 20:20:46 +08:00
|
|
|
#elif ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T )
|
2013-10-07 07:57:01 +08:00
|
|
|
RETSIGTYPE zm_die_handler(int signal, siginfo_t * info, void *ucontext)
|
2006-04-05 20:20:46 +08:00
|
|
|
#else
|
2013-10-07 07:57:01 +08:00
|
|
|
RETSIGTYPE zm_die_handler(int signal)
|
2006-04-05 20:20:46 +08:00
|
|
|
#endif
|
|
|
|
{
|
2013-10-07 07:57:01 +08:00
|
|
|
void *cr2 = 0;
|
|
|
|
void *ip = 0;
|
2013-10-07 07:37:50 +08:00
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
// Print signal number and also signal text if available
|
|
|
|
if (signal == SIGABRT) {
|
2008-07-23 03:54:01 +08:00
|
|
|
#if HAVE_STRSIGNAL
|
2013-10-07 07:57:01 +08:00
|
|
|
Info("Got signal %d (%s), exiting and forcing backtrace",
|
|
|
|
signal, strsignal(signal));
|
|
|
|
#else // HAVE_STRSIGNAL
|
|
|
|
Error("Got signal %d, exiting and forcing backtrace", signal);
|
|
|
|
#endif // HAVE_STRSIGNAL
|
|
|
|
} else {
|
2009-02-17 20:27:03 +08:00
|
|
|
#if HAVE_STRSIGNAL
|
2013-10-07 07:57:01 +08:00
|
|
|
Info("Got signal %d (%s), crashing", signal, strsignal(signal));
|
|
|
|
#else // HAVE_STRSIGNAL
|
|
|
|
Error("Got signal %d, crashing", signal);
|
|
|
|
#endif // HAVE_STRSIGNAL
|
|
|
|
}
|
2006-04-05 20:20:46 +08:00
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
// Get signal address and instruction pointer if available
|
2013-10-07 07:37:50 +08:00
|
|
|
#if (( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) || HAVE_STRUCT_SIGCONTEXT )
|
2013-10-06 23:26:33 +08:00
|
|
|
#if HAVE_STRUCT_SIGCONTEXT
|
|
|
|
#if HAVE_STRUCT_SIGCONTEXT_RIP
|
2013-10-07 07:57:01 +08:00
|
|
|
cr2 = (void *)context.cr2;
|
|
|
|
ip = (void *)context.rip;
|
2013-10-06 23:26:33 +08:00
|
|
|
#elif HAVE_STRUCT_SIGCONTEXT_EIP
|
2013-10-07 07:57:01 +08:00
|
|
|
cr2 = (void *)context.cr2;
|
|
|
|
ip = (void *)context.eip;
|
2013-10-06 23:26:33 +08:00
|
|
|
#else
|
2013-10-07 07:57:01 +08:00
|
|
|
cr2 = (void *)context.cr2;
|
|
|
|
#endif // HAVE_STRUCT_SIGCONTEXT_*
|
2006-04-05 20:20:46 +08:00
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
#else // HAVE_STRUCT_SIGCONTEXT
|
|
|
|
if (info && ucontext) {
|
|
|
|
ucontext_t *uc = (ucontext_t *) ucontext;
|
2013-10-06 23:26:33 +08:00
|
|
|
#if defined(__x86_64__)
|
2013-10-07 07:37:50 +08:00
|
|
|
cr2 = info->si_addr;
|
2013-10-07 07:57:01 +08:00
|
|
|
ip = (void *)(uc->uc_mcontext.gregs[REG_RIP]);
|
2013-10-06 23:26:33 +08:00
|
|
|
#else
|
2013-10-07 07:37:50 +08:00
|
|
|
cr2 = info->si_addr;
|
2013-10-07 07:57:01 +08:00
|
|
|
ip = (void *)(uc->uc_mcontext.gregs[REG_EIP]);
|
|
|
|
#endif // defined(__x86_64__)
|
2006-04-05 20:20:46 +08:00
|
|
|
}
|
2013-10-07 07:57:01 +08:00
|
|
|
#endif // HAVE_STRUCT_SIGCONTEXT
|
|
|
|
#endif // (( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) || HAVE_STRUCT_SIGCONTEXT )
|
|
|
|
|
|
|
|
// Print the signal address and instruction pointer if available
|
|
|
|
if (cr2) {
|
|
|
|
if (ip) {
|
|
|
|
Error("Signal address is %p, from %p", cr2, ip);
|
|
|
|
} else {
|
|
|
|
Error("Signal address is %p, no instruction pointer",
|
|
|
|
cr2);
|
|
|
|
}
|
2013-10-07 07:37:50 +08:00
|
|
|
}
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
// Print backtrace if enabled and available
|
2013-10-07 07:37:50 +08:00
|
|
|
#if ( !defined(ZM_NO_CRASHTRACE) && HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS )
|
2013-10-07 07:57:01 +08:00
|
|
|
void *trace[TRACE_SIZE];
|
|
|
|
int trace_size = 0;
|
|
|
|
trace_size = backtrace(trace, TRACE_SIZE);
|
|
|
|
|
|
|
|
char cmd[1024] = "addr2line -e ";
|
|
|
|
char *cmd_ptr = cmd + strlen(cmd);
|
|
|
|
|
|
|
|
char **messages = backtrace_symbols(trace, trace_size);
|
|
|
|
cmd_ptr += snprintf(cmd_ptr, sizeof(cmd) - (cmd_ptr - cmd), "%s", self);
|
|
|
|
|
|
|
|
// Skip the last entries that have no text, they probably point here
|
|
|
|
bool found_last = false;
|
|
|
|
for (int i = 1; i < trace_size; i++) {
|
|
|
|
if ((!found_last && messages[i][0] != '[') || found_last) {
|
|
|
|
found_last = true;
|
|
|
|
Error("Backtrace: %s", messages[i]);
|
|
|
|
cmd_ptr +=
|
|
|
|
snprintf(cmd_ptr, sizeof(cmd) - (cmd_ptr - cmd),
|
|
|
|
" %p", trace[i]);
|
|
|
|
}
|
2013-10-06 23:26:33 +08:00
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
}
|
|
|
|
Info("Backtrace complete, please execute the following command for more information");
|
|
|
|
Info(cmd);
|
|
|
|
#endif // ( !defined(ZM_NO_CRASHTRACE) && HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS )
|
2006-04-05 20:20:46 +08:00
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
exit(signal);
|
2006-04-05 20:20:46 +08:00
|
|
|
}
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
void zmSetHupHandler(SigHandler * handler)
|
2006-04-05 20:20:46 +08:00
|
|
|
{
|
|
|
|
sigset_t block_set;
|
2013-10-07 07:57:01 +08:00
|
|
|
sigemptyset(&block_set);
|
2006-04-05 20:20:46 +08:00
|
|
|
struct sigaction action, old_action;
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
action.sa_handler = (SigHandler *) handler;
|
2006-04-05 20:20:46 +08:00
|
|
|
action.sa_mask = block_set;
|
|
|
|
action.sa_flags = 0;
|
2013-10-07 07:57:01 +08:00
|
|
|
sigaction(SIGHUP, &action, &old_action);
|
2006-04-05 20:20:46 +08:00
|
|
|
}
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
void zmSetTermHandler(SigHandler * handler)
|
2006-04-05 20:20:46 +08:00
|
|
|
{
|
|
|
|
sigset_t block_set;
|
2013-10-07 07:57:01 +08:00
|
|
|
sigemptyset(&block_set);
|
2006-04-05 20:20:46 +08:00
|
|
|
struct sigaction action, old_action;
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
action.sa_handler = (SigHandler *) handler;
|
2006-04-05 20:20:46 +08:00
|
|
|
action.sa_mask = block_set;
|
|
|
|
action.sa_flags = 0;
|
2013-10-07 07:57:01 +08:00
|
|
|
sigaction(SIGTERM, &action, &old_action);
|
2006-04-05 20:20:46 +08:00
|
|
|
}
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
void zmSetDieHandler(SigHandler * handler)
|
2006-04-05 20:20:46 +08:00
|
|
|
{
|
|
|
|
sigset_t block_set;
|
2013-10-07 07:57:01 +08:00
|
|
|
sigemptyset(&block_set);
|
2006-04-05 20:20:46 +08:00
|
|
|
struct sigaction action, old_action;
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
action.sa_handler = (SigHandler *) handler;
|
2006-04-05 20:20:46 +08:00
|
|
|
action.sa_mask = block_set;
|
|
|
|
action.sa_flags = 0;
|
|
|
|
|
2013-10-07 07:57:01 +08:00
|
|
|
sigaction(SIGBUS, &action, &old_action);
|
|
|
|
sigaction(SIGSEGV, &action, &old_action);
|
|
|
|
sigaction(SIGABRT, &action, &old_action);
|
|
|
|
sigaction(SIGILL, &action, &old_action);
|
|
|
|
sigaction(SIGFPE, &action, &old_action);
|
2006-04-05 20:20:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void zmSetDefaultHupHandler()
|
|
|
|
{
|
2013-10-07 07:57:01 +08:00
|
|
|
zmSetHupHandler((SigHandler *) zm_hup_handler);
|
2006-04-05 20:20:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void zmSetDefaultTermHandler()
|
|
|
|
{
|
2013-10-07 07:57:01 +08:00
|
|
|
zmSetTermHandler((SigHandler *) zm_term_handler);
|
2006-04-05 20:20:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void zmSetDefaultDieHandler()
|
|
|
|
{
|
2013-10-07 07:57:01 +08:00
|
|
|
if (config.dump_cores) {
|
|
|
|
// Do nothing
|
|
|
|
} else {
|
|
|
|
zmSetDieHandler((SigHandler *) zm_die_handler);
|
|
|
|
}
|
2006-04-05 20:20:46 +08:00
|
|
|
}
|