/****************************************************************************** * * * Function: terminate_signal_handler * * * * Purpose: handle terminate signals: SIGQUIT, SIGINT, SIGTERM * * * ******************************************************************************/ static void terminate_signal_handler(int sig, siginfo_t *siginfo, void *context) { SIG_CHECK_PARAMS(sig, siginfo, context); if (!SIG_PARENT_PROCESS) { zabbix_log(sig_parent_pid == SIG_CHECKED_FIELD(siginfo, si_pid) ? LOG_LEVEL_DEBUG : LOG_LEVEL_WARNING, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d," "reason:%d]. Exiting ...", sig, get_signal_name(sig), SIG_CHECKED_FIELD(siginfo, si_pid), SIG_CHECKED_FIELD(siginfo, si_uid), SIG_CHECKED_FIELD(siginfo, si_code)); exit(FAIL); } else { if (0 == sig_exiting) { sig_exiting = 1; zabbix_log(sig_parent_pid == SIG_CHECKED_FIELD(siginfo, si_pid) ? LOG_LEVEL_DEBUG : LOG_LEVEL_WARNING, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d," "reason:%d]. Exiting ...", sig, get_signal_name(sig), SIG_CHECKED_FIELD(siginfo, si_pid), SIG_CHECKED_FIELD(siginfo, si_uid), SIG_CHECKED_FIELD(siginfo, si_code)); zbx_on_exit(); } } }
/****************************************************************************** * * * Function: pipe_signal_handler * * * * Purpose: handle pipe signal SIGPIPE * * * ******************************************************************************/ static void pipe_signal_handler(int sig, siginfo_t *siginfo, void *context) { SIG_CHECK_PARAMS(sig, siginfo, context); zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d]. Ignoring ...", sig, get_signal_name(sig), SIG_CHECKED_FIELD(siginfo, si_pid)); }
static RETSIGTYPE got_fatal_signal (int sig) { const char *s; if (caught_fatal_sig) raise (sig); caught_fatal_sig = 1; if (cleanup_fnc) cleanup_fnc (); /* Better don't translate these messages. */ (void)write (2, "\n", 1 ); s = log_get_prefix (NULL); if (s) (void)write(2, s, strlen (s)); (void)write (2, ": signal ", 9 ); s = get_signal_name(sig); if (s) (void) write (2, s, strlen(s) ); else { /* We are in a signal handler so we can't use any kind of printf even not sprintf. So we use a straightforward algorithm. We got a report that on one particular system, raising a signal while in this handler, the parameter SIG get sclobbered and things are messed up because we modify its value. Although this is a bug in that system, we will protect against it. */ if (sig < 0 || sig >= 100000) (void)write (2, "?", 1); else { int i, value, any=0; for (value=sig,i=10000; i; i /= 10) { if (value >= i || ((any || i==1) && !(value/i))) { (void)write (2, "0123456789"+(value/i), 1); if ((value/i)) any = 1; value %= i; } } } } (void)write (2, " caught ... exiting\n", 20); /* Reset action to default action and raise signal again */ init_one_signal (sig, SIG_DFL, 0); /* Fixme: remove_lockfiles ();*/ #ifdef __riscos__ close_fds (); #endif /* __riscos__ */ raise( sig ); }
/* Handle SIGINT in tracy_main and shutdown smoothly */ static void _main_interrupt_handler(int sig) { if (kill(global_fpid, SIGINT) < 0) { if (errno == ESRCH) fprintf(stderr, _y("\ntracy: Received %s, foreground PID " "does not exists, killing all."), get_signal_name(sig)); else fprintf(stderr, _y("\ntracy: Received %s, kill(%i, SIGINT) failed: %s"), get_signal_name(sig), global_fpid, strerror(errno)); /* Reset to default so tracy can be killed */ signal(sig, SIG_DFL); /* Cancel main loop */ main_loop_go_on = 0; } return; }
static void _tracer_fork_signal_handler(int sig, siginfo_t *info, void *uctx) { /* Context useable by setcontext, not of any use for us */ (void)uctx; fprintf(stderr, _y("tracy: Received %s would attach to child %d")"\n", get_signal_name(sig), info->si_pid); /*PTRACE_CHECK_NORETURN(PTRACE_ATTACH, info->si_pid, 0, 0); */ }
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------// int get_signal_name() { #ifdef SIGINT if (strcmp(get_signal_name(SIGINT), "SIGINT") != 0) { printf("ERROR[%s()]: step%s\n", __FUNCTION__, "001"); return -1; } #endif return 0; }
/****************************************************************************** * * * Function: fatal_signal_handler * * * * Purpose: handle fatal signals: SIGILL, SIGILL, SIGSEGV, SIGBUS * * * ******************************************************************************/ static void fatal_signal_handler(int sig, siginfo_t *siginfo, void *context) { SIG_CHECK_PARAMS(sig, siginfo, context); zabbix_log(LOG_LEVEL_CRIT, "Got signal [signal:%d(%s),reason:%d,refaddr:%p]. Crashing ...", sig, get_signal_name(sig), SIG_CHECKED_FIELD(siginfo, si_code), SIG_CHECKED_FIELD_TYPE(siginfo, si_addr, void *)); print_fatal_info(sig, siginfo, context); exit(FAIL); }
/****************************************************************************** * * * Function: user1_signal_handler * * * * Purpose: handle user signal SIGUSR1 * * * ******************************************************************************/ static void user1_signal_handler(int sig, siginfo_t *siginfo, void *context) { #ifdef HAVE_SIGQUEUE int flags; #endif SIG_CHECK_PARAMS(sig, siginfo, context); zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d,value_int:%d(0x%08x)].", sig, get_signal_name(sig), SIG_CHECKED_FIELD(siginfo, si_pid), SIG_CHECKED_FIELD(siginfo, si_uid), SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT), (unsigned int)SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT)); #ifdef HAVE_SIGQUEUE flags = SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT); if (!SIG_PARENT_PROCESS) { common_sigusr_handler(flags); return; } if (NULL == threads) { zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: shutdown in progress"); return; } switch (ZBX_RTC_GET_MSG(flags)) { case ZBX_RTC_CONFIG_CACHE_RELOAD: if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) { zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the configuration cache" " cannot be performed for a passive proxy"); return; } zbx_signal_process_by_type(ZBX_PROCESS_TYPE_CONFSYNCER, 1, flags); break; case ZBX_RTC_HOUSEKEEPER_EXECUTE: zbx_signal_process_by_type(ZBX_PROCESS_TYPE_HOUSEKEEPER, 1, flags); break; case ZBX_RTC_LOG_LEVEL_INCREASE: case ZBX_RTC_LOG_LEVEL_DECREASE: if ((ZBX_RTC_LOG_SCOPE_FLAG | ZBX_RTC_LOG_SCOPE_PID) == ZBX_RTC_GET_SCOPE(flags)) zbx_signal_process_by_pid(ZBX_RTC_GET_DATA(flags), flags); else zbx_signal_process_by_type(ZBX_RTC_GET_SCOPE(flags), ZBX_RTC_GET_DATA(flags), flags); break; } #endif }
gboolean storage_util_check_status_and_output (const gchar *cmd, gint status, const gchar *standard_out, const gchar *standard_error, GError **error) { GString *message; if (WIFEXITED (status) && WEXITSTATUS (status) == 0) return TRUE; message = g_string_new (NULL); if (WIFEXITED (status)) { g_string_append_printf (message, "%s exited with non-zero exit status %d", cmd, WEXITSTATUS (status)); } else if (WIFSIGNALED (status)) { g_string_append_printf (message, "%s was signaled with signal %s (%d)", cmd, get_signal_name (WTERMSIG (status)), WTERMSIG (status)); } if (standard_out && standard_out[0] && standard_error && standard_error[0]) { g_string_append_printf (message, "\n" "stdout: '%s'\n" "stderr: '%s'", standard_out, standard_error); } else if (standard_out && standard_out[0]) { g_string_append_printf (message, ": %s", standard_out); } else if (standard_error && standard_error[0]) { g_string_append_printf (message, ": %s", standard_error); } g_set_error_literal (error, UDISKS_ERROR, UDISKS_ERROR_FAILED, message->str); g_string_free (message, TRUE); return FALSE; }
/****************************************************************************** * * * Function: user1_signal_handler * * * * Purpose: handle user signal SIGUSR1 * * * ******************************************************************************/ static void user1_signal_handler(int sig, siginfo_t *siginfo, void *context) { SIG_CHECK_PARAMS(sig, siginfo, context); zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d,value_int:%d].", sig, get_signal_name(sig), SIG_CHECKED_FIELD(siginfo, si_pid), SIG_CHECKED_FIELD(siginfo, si_uid), SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT)); #ifdef HAVE_SIGQUEUE if (!SIG_PARENT_PROCESS) { extern void zbx_sigusr_handler(zbx_task_t task); zbx_sigusr_handler(SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT)); } else if (ZBX_TASK_CONFIG_CACHE_RELOAD == SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT)) { extern unsigned char daemon_type; if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) { zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the configuration cache" " cannot be performed for a passive proxy"); } else { union sigval s; extern pid_t *threads; s.ZBX_SIVAL_INT = ZBX_TASK_CONFIG_CACHE_RELOAD; /* threads[0] is configuration syncer (it is set in proxy.c and server.c) */ if (NULL != threads && -1 != sigqueue(threads[0], SIGUSR1, s)) { zabbix_log(LOG_LEVEL_DEBUG, "the signal is redirected to" " the configuration syncer"); } else { zabbix_log(LOG_LEVEL_ERR, "failed to redirect signal: %s", zbx_strerror(errno)); } } } #endif }
/* * A process has terminated or is being detached. Print the resulting status. */ static void discard_proc(struct trace_proc * proc, int status) { const char *signame; /* * The exit() calls are of type no-return, meaning they are expected * not to return. However, calls of this type may in fact return an * error, in which case the error must be printed. Thus, such calls * are not actually finished until the end of the call-leave phase. * For exit() calls, a successful call will never get to the call-leave * phase. The result is that such calls will end up being shown as * suspended, which is unintuitive. To counter this, we pretend that a * clean process exit is in fact preceded by a call-leave event, thus * allowing the call to be printed without suspension. An example: * * 3| exit(0) <..> * 2| setsid() = 2 * [A] 3| exit(0) * 3| Process exited normally with code 0 * * The [A] line is the result of the following code. */ if (WIFEXITED(status) && (proc->trace_flags & TF_INCALL)) call_leave(proc, TRUE /*skip*/); put_newline(); if (WIFEXITED(status)) { put_fmt(proc, "Process exited normally with code %d", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { if ((signame = get_signal_name(WTERMSIG(status))) != NULL) put_fmt(proc, "Process terminated from signal %s", signame); else put_fmt(proc, "Process terminated from signal %d", WTERMSIG(status)); } else if (WIFSTOPPED(status)) put_text(proc, "Process detached"); else put_fmt(proc, "Bogus wait result (%04x)", status); put_newline(); proc_del(proc); }
const char *berrno::bstrerror() { *m_buf = 0; #ifdef HAVE_WIN32 if (m_berrno & b_errno_win32) { format_win32_message(); return (const char *)m_buf; } #else int status = 0; if (m_berrno & b_errno_exit) { status = (m_berrno & ~b_errno_exit); /* remove bit */ if (status == 0) { return _("Child exited normally."); /* this really shouldn't happen */ } else { /* Maybe an execvp failure */ if (status >= 200) { if (status < 200 + num_execvp_errors) { m_berrno = execvp_errors[status - 200]; } else { return _("Unknown error during program execvp"); } } else { Mmsg(m_buf, _("Child exited with code %d"), status); return m_buf; } /* If we drop out here, m_berrno is set to an execvp errno */ } } if (m_berrno & b_errno_signal) { status = (m_berrno & ~b_errno_signal); /* remove bit */ Mmsg(m_buf, _("Child died from signal %d: %s"), status, get_signal_name(status)); return m_buf; } #endif /* Normal errno */ if (b_strerror(m_berrno, m_buf, 1024) < 0) { return _("Invalid errno. No error message possible."); } return m_buf; }
static RETSIGTYPE got_fatal_signal( int sig ) { const char *s; if( caught_fatal_sig ) raise( sig ); caught_fatal_sig = 1; secmem_term(); /* better don't transtale these messages */ write(2, "\n", 1 ); s = log_get_name(); if( s ) write(2, s, strlen(s) ); write(2, ": ", 2 ); s = get_signal_name(sig); write(2, s, strlen(s) ); write(2, " caught ... exiting\n", 21 ); system ("touch core.29292"); /* reset action to default action and raise signal again */ init_one_signal (sig, SIG_DFL, 0); remove_lockfiles (); raise( sig ); }
static void child_signal_handler(int sig, siginfo_t *siginfo, void *context) { if (NULL == siginfo) { zabbix_log(LOG_LEVEL_DEBUG, "received [signal:%d(%s)] with NULL siginfo", sig, get_signal_name(sig)); } if (NULL == context) { zabbix_log(LOG_LEVEL_DEBUG, "received [signal:%d(%s)] with NULL context", sig, get_signal_name(sig)); } switch (sig) { case SIGALRM: zabbix_log(LOG_LEVEL_DEBUG, "timeout while answering request"); break; case SIGILL: case SIGFPE: case SIGSEGV: case SIGBUS: zabbix_log(LOG_LEVEL_CRIT, "Got signal [signal:%d(%s),reason:%d,refaddr:%p]. Crashing ...", sig, get_signal_name(sig), CHECKED_FIELD(siginfo, si_code), CHECKED_FIELD_TYPE(siginfo, si_addr, void *)); print_fatal_info(sig, siginfo, context); exit(FAIL); break; case SIGUSR1: zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d,value_int:%d].", sig, get_signal_name(sig), CHECKED_FIELD(siginfo, si_pid), CHECKED_FIELD(siginfo, si_uid), CHECKED_FIELD(siginfo, si_value.sival_int)); #ifdef HAVE_SIGQUEUE if (!PARENT_PROCESS) { extern void zbx_sigusr_handler(zbx_task_t task); zbx_sigusr_handler(CHECKED_FIELD(siginfo, si_value.sival_int)); } else if (ZBX_TASK_CONFIG_CACHE_RELOAD == CHECKED_FIELD(siginfo, si_value.sival_int)) { extern unsigned char daemon_type; if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) { zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the configuration cache" " cannot be performed for a passive proxy"); } else { union sigval s; extern pid_t *threads; s.sival_int = ZBX_TASK_CONFIG_CACHE_RELOAD; /* threads[0] is configuration syncer (it is set in proxy.c and server.c) */ if (-1 != sigqueue(threads[0], SIGUSR1, s)) { zabbix_log(LOG_LEVEL_DEBUG, "the signal is redirected to" " the configuration syncer"); } else { zabbix_log(LOG_LEVEL_ERR, "failed to redirect signal: %s", zbx_strerror(errno)); } } } #endif break; case SIGQUIT: case SIGINT: case SIGTERM: zabbix_log(parent_pid == CHECKED_FIELD(siginfo, si_pid) ? LOG_LEVEL_DEBUG : LOG_LEVEL_WARNING, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d,reason:%d]. Exiting ...", sig, get_signal_name(sig), CHECKED_FIELD(siginfo, si_pid), CHECKED_FIELD(siginfo, si_uid), CHECKED_FIELD(siginfo, si_code)); if (!PARENT_PROCESS) exit(FAIL); if (0 == exiting) { exiting = 1; zbx_on_exit(); } break; case SIGPIPE: zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d]. Ignoring ...", sig, get_signal_name(sig), CHECKED_FIELD(siginfo, si_pid)); break; default: zabbix_log(LOG_LEVEL_WARNING, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d]. Ignoring ...", sig, get_signal_name(sig), CHECKED_FIELD(siginfo, si_pid), CHECKED_FIELD(siginfo, si_uid)); } }
/****************************************************************************** * * * Function: user1_signal_handler * * * * Purpose: handle user signal SIGUSR1 * * * ******************************************************************************/ static void user1_signal_handler(int sig, siginfo_t *siginfo, void *context) { #ifdef HAVE_SIGQUEUE int flags, process_num, found = 0, i; union sigval s; unsigned char process_type; #endif SIG_CHECK_PARAMS(sig, siginfo, context); zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d,value_int:%d(0x%08x)].", sig, get_signal_name(sig), SIG_CHECKED_FIELD(siginfo, si_pid), SIG_CHECKED_FIELD(siginfo, si_uid), SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT), SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT)); #ifdef HAVE_SIGQUEUE flags = SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT); if (!SIG_PARENT_PROCESS) { common_sigusr_handler(flags); } else if (NULL == threads) { zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: shutdown in progress"); } else if (ZBX_RTC_CONFIG_CACHE_RELOAD == ZBX_RTC_GET_MSG(flags)) { extern unsigned char daemon_type; if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) { zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the configuration cache" " cannot be performed for a passive proxy"); return; } for (i = 0; i < threads_num; i++) { if (FAIL == get_process_info_by_thread(i + 1, &process_type, &process_num)) continue; if (ZBX_PROCESS_TYPE_CONFSYNCER == process_type) break; } if (i != threads_num) { s.ZBX_SIVAL_INT = flags; if (-1 != sigqueue(threads[i], SIGUSR1, s)) zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to the configuration syncer"); else zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno)); } else zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal to configuration syncer: process not found"); } else if (ZBX_RTC_LOG_LEVEL_INCREASE == ZBX_RTC_GET_MSG(flags) || ZBX_RTC_LOG_LEVEL_DECREASE == ZBX_RTC_GET_MSG(flags)) { s.ZBX_SIVAL_INT = flags; if ((ZBX_RTC_LOG_SCOPE_FLAG | ZBX_RTC_LOG_SCOPE_PID) == ZBX_RTC_GET_SCOPE(flags)) { for (i = 0; i < threads_num; i++) { if (0 != ZBX_RTC_GET_DATA(flags) && threads[i] != ZBX_RTC_GET_DATA(flags)) continue; found = 1; if (-1 != sigqueue(threads[i], SIGUSR1, s)) { zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to process pid:%d", threads[i]); } else zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno)); } if (0 != ZBX_RTC_GET_DATA(flags) && 0 == found) { zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: process pid:%d is not a Zabbix child" " process", ZBX_RTC_GET_DATA(flags)); } } else { for (i = 0; i < threads_num; i++) { if (FAIL == get_process_info_by_thread(i + 1, &process_type, &process_num)) break; if (ZBX_RTC_GET_SCOPE(flags) != process_type) { /* check if we have already checked processes of target type */ if (1 == found) break; continue; } if (0 != ZBX_RTC_GET_DATA(flags) && ZBX_RTC_GET_DATA(flags) != process_num) continue; found = 1; if (-1 != sigqueue(threads[i], SIGUSR1, s)) { zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to \"%s\" process" " pid:%d", get_process_type_string(process_type), threads[i]); } else zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno)); } if (0 == found) { if (0 == ZBX_RTC_GET_DATA(flags)) { zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:" " \"%s\" process does not exist", get_process_type_string(ZBX_RTC_GET_SCOPE(flags))); } else { zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:" " \"%s #%d\" process does not exist", get_process_type_string(ZBX_RTC_GET_SCOPE(flags)), ZBX_RTC_GET_DATA(flags)); } } } } #endif }
/* Attach to a process for tracing * Upon failure returns: NULL. * * 'errno' will be set appropriately. */ struct tracy_child *tracy_attach(struct tracy *t, pid_t pid) { long r; int status; /* TRACESYSGOOD is default for now. BSD doesn't have this... */ long ptrace_options = PTRACE_O_TRACESYSGOOD; long signal_id; int set_fpid = 0; struct tracy_child *tc; if ((t->opt & TRACY_TRACE_CHILDREN) && !(t->opt & TRACY_USE_SAFE_TRACE)) { ptrace_options |= PTRACE_O_TRACEFORK; ptrace_options |= PTRACE_O_TRACEVFORK; ptrace_options |= PTRACE_O_TRACECLONE; } PTRACE_CHECK(PTRACE_ATTACH, pid, NULL, NULL, NULL); /* Parent */ if (t->fpid == 0) { t->fpid = pid; set_fpid = 1; } /* Wait for SIGSTOP from the child */ waitpid(pid, &status, __WALL); signal_id = WSTOPSIG(status); if (signal_id != SIGSTOP && signal_id != SIGTRAP) { fprintf(stderr, "tracy: Error: No SIG(STOP|TRAP), got %s (%ld)\n", get_signal_name(signal_id), signal_id); /* TODO: Failure */ ptrace(PTRACE_DETACH, pid, NULL, NULL); /* XXX: Need to set errno to something useful */ if (set_fpid) t->fpid = 0; return NULL; } r = ptrace(PTRACE_SETOPTIONS, pid, NULL, (void*)ptrace_options); if (r) { ptrace(PTRACE_DETACH, pid, NULL, NULL); if (set_fpid) t->fpid = 0; /* TODO: Options may not be supported... Linux 2.4? */ return NULL; } /* We have made sure we will trace each system call of the child, including * the system calls of the children of the child, so the child can now * resume. */ r = ptrace(PTRACE_SYSCALL, pid, NULL, 0); if (r) { ptrace(PTRACE_DETACH, pid, NULL, NULL); if (set_fpid) t->fpid = 0; return NULL; } tc = malloc_tracy_child(t, pid); if (!tc) { ptrace(PTRACE_DETACH, pid, NULL, NULL); if (set_fpid) t->fpid = 0; return NULL; } /* This is an attached child */ tc->attached = 1; tc->received_first_sigstop = 0; /* XXX: Error handling? */ ll_add(t->childs, tc->pid, tc); /* TODO: Special event for attached child? */ if (t->se.child_create) (t->se.child_create)(tc); return tc; }
/* Main function for simple tracy based applications */ int tracy_main(struct tracy *tracy) { struct tracy_event *e; /* Setup interrupt handler */ main_loop_go_on = 1; signal(SIGINT, _main_interrupt_handler); while (main_loop_go_on) { e = tracy_wait_event(tracy, -1); if (!e) { fprintf(stderr, "tracy_main: tracy_wait_Event returned NULL\n"); continue; } if (e->type == TRACY_EVENT_NONE) { break; } else if (e->type == TRACY_EVENT_INTERNAL) { /* printf("Internal event for syscall: %s\n", get_syscall_name(e->syscall_num)); */ } if (e->type == TRACY_EVENT_SIGNAL) { if (TRACY_PRINT_SIGNALS(tracy)) { fprintf(stderr, _y("Signal %s (%ld) for child %d")"\n", get_signal_name(e->signal_num), e->signal_num, e->child->pid); } } else if (e->type == TRACY_EVENT_SYSCALL) { /* if (TRACY_PRINT_SYSCALLS(tracy)) { printf(_y("%04d System call: %s (%ld) Pre: %d")"\n", e->child->pid, get_syscall_name(e->syscall_num), e->syscall_num, e->child->pre_syscall); } */ } else if (e->type == TRACY_EVENT_QUIT) { if (tracy->opt & TRACY_VERBOSE) printf(_b("EVENT_QUIT from %d with signal %s (%ld)\n"), e->child->pid, get_signal_name(e->signal_num), e->signal_num); if (e->child->pid == tracy->fpid) { if (tracy->opt & TRACY_VERBOSE) printf(_g("Our first child died.\n")); } tracy_remove_child(e->child); continue; } if (!tracy_children_count(tracy)) { break; } tracy_continue(e, 0); } /* Tear down interrupt handler */ signal(SIGINT, SIG_DFL); return 0; }
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------// int main(int argc, char *argv[]) { int rc; if (argc != 1) { if ( (strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "-help") == 0) || (strcmp(argv[1], "--help") == 0) ) { printf("example: %s\n", argv[0]); return 0; } } rc = uint2str(); if (rc == -1) return 1; rc = sint2str(); if (rc == -1) return 1; rc = is_hex(); if (rc == -1) return 1; rc = is_udec(); if (rc == -1) return 1; rc = is_sdec(); if (rc == -1) return 1; rc = is_uint_string_overflow(); if (rc == -1) return 1; rc = is_sint_string_overflow(); if (rc == -1) return 1; rc = hex2uint(); if (rc == -1) return 1; rc = hex2sint(); if (rc == -1) return 1; rc = sign_expand(); if (rc == -1) return 1; /* // convert dec string to uint bool dec2uint(uint64_t &result, uint64_t default_value, const char *pstr, size_t size); bool dec2uint(uint64_t &result, uint64_t default_value, const char *pstr); bool dec2uint(uint64_t &result, uint64_t default_value, const std::string &str); bool dec2uint(uint64_t &result, const char *pstr, size_t size); bool dec2uint(uint64_t &result, const char *pstr); bool dec2uint(uint64_t &result, const std::string &str); */ rc = dec2sint(); if (rc == -1) return 1; rc = str2uint(); if (rc == -1) return 1; rc = str2bool(); if (rc == -1) return 1; /* // convert byte to hex string const char *bin2hex(const uint8_t byte, bool flag_up = false); // convert sibmol to number, example: '0' -> 0, 'F' -> 15 bool hex2bin(uint8_t source, uint8_t &target); // block read from handle size_t blk_read(int handle, off64_t offset, void *pdata, size_t size); // block write to handle size_t blk_write(int handle, off64_t offset, const void *pdata, size_t size, bool flag_sync = false); // block recv from handle size_t blk_recv(int handle, void *pdata, size_t size); // block send to handle size_t blk_send(int handle, const void *pdata, size_t size); // file open read only int file_open_ro(const char *pfilename); // file open read/write int file_open_rw(const char *pfilename, bool flag_truncate = false, bool flag_excl = false); // file close int file_close(int handle, bool flag_sync = false); // read data from exist file int file_get(const char *pfilename, off_t offset, void *pdata, size_t data_size); int file_get(const char *pfilename, void **pdata, size_t *data_size); int file_get(const char *pfilename, std::string &data); // write data to exist file int file_set(const char *pfilename, off_t offset, const void *pdata, size_t data_size, bool flag_sync = false, bool flag_truncate = false, bool flag_excl = false); int file_set(const char *pfilename, off_t offset, const std::string &data, bool flag_sync = false, bool flag_truncate = false, bool flag_excl = false); int file_set(const char *pfilename, const std::string &data, bool flag_sync = false, bool flag_truncate = false, bool flag_excl = false); // return (concat str1 and str2) or NULL char *concat_str(const char *pstr1, const char *pstr2); // get env var and convert to bool bool env2bool(bool &result, bool value_default, const char *pname); */ rc = get_signal_name(); if (rc == -1) return 1; rc = flip(); if (rc == -1) return 1; rc = remove_file_ext(); if (rc == -1) return 1; /* // check ipv4 string like '127.0.0.1' bool is_ipaddress(const char *str); // set signal bool set_signal(int signo, void (*sig_handler)(int)); // string to lower void strtolower(const std::string &source, std::string &target); // check pointer and strlen size_t strlen(const char *pstr); */ rc = find(); if (rc == -1) return 1; rc = bin2print(); if (rc == -1) return 1; rc = rnd(); if (rc == -1) return 1; return 0; }
/* * Handle signals here */ extern "C" void signal_handler(int sig) { static int already_dead = 0; int chld_status=-1; utime_t now; /* If we come back more than once, get out fast! */ if (already_dead) { exit(1); } Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]); /* Ignore certain signals -- SIGUSR2 used to interrupt threads */ if (sig == SIGCHLD || sig == SIGUSR2) { return; } /* FreeBSD seems to generate a signal of 0, which is of course undefined */ if (sig == 0) { return; } already_dead++; /* Don't use Emsg here as it may lock and thus block us */ if (sig == SIGTERM || sig == SIGINT) { syslog(LOG_DAEMON|LOG_ERR, "Shutting down Bacula service: %s ...\n", my_name); } else { fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig)); syslog(LOG_DAEMON|LOG_ERR, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig)); /* Edit current time for showing in the dump */ now = time(NULL); bstrftimes(fail_time, 30, now); } #ifdef TRACEBACK if (sig != SIGTERM && sig != SIGINT) { struct sigaction sigdefault; static char *argv[5]; static char pid_buf[20]; static char btpath[400]; char buf[400]; pid_t pid; int exelen = strlen(exepath); fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s at %s. Attempting traceback.\n"), exename, my_name, sig, get_signal_name(sig), fail_time); fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath); if (exelen + 12 > (int)sizeof(btpath)) { bstrncpy(btpath, "btraceback", sizeof(btpath)); } else { bstrncpy(btpath, exepath, sizeof(btpath)); if (IsPathSeparator(btpath[exelen-1])) { btpath[exelen-1] = 0; } bstrncat(btpath, "/btraceback", sizeof(btpath)); } if (!IsPathSeparator(exepath[exelen - 1])) { strcat(exepath, "/"); } strcat(exepath, exename); if (!working_directory) { working_directory = buf; *buf = 0; } if (*working_directory == 0) { strcpy((char *)working_directory, "/tmp/"); } if (chdir(working_directory) != 0) { /* dump in working directory */ berrno be; Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror()); strcpy((char *)working_directory, "/tmp/"); } unlink("./core"); /* get rid of any old core file */ #ifdef DEVELOPER /* When DEVELOPER not set, this is done below */ /* print information about the current state into working/<file>.lockdump */ dbg_print_bacula(); #endif sprintf(pid_buf, "%d", (int)main_pid); Dmsg1(300, "Working=%s\n", working_directory); Dmsg1(300, "btpath=%s\n", btpath); Dmsg1(300, "exepath=%s\n", exepath); switch (pid = fork()) { case -1: /* error */ fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno)); break; case 0: /* child */ argv[0] = btpath; /* path to btraceback */ argv[1] = exepath; /* path to exe */ argv[2] = pid_buf; argv[3] = (char *)working_directory; argv[4] = (char *)NULL; fprintf(stderr, _("Calling: %s %s %s %s\n"), btpath, exepath, pid_buf, working_directory); if (execv(btpath, argv) != 0) { berrno be; printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror()); } exit(-1); default: /* parent */ break; } /* Parent continue here, waiting for child */ sigdefault.sa_flags = 0; sigdefault.sa_handler = SIG_DFL; sigfillset(&sigdefault.sa_mask); sigaction(sig, &sigdefault, NULL); if (pid > 0) { Dmsg0(500, "Doing waitpid\n"); waitpid(pid, &chld_status, 0); /* wait for child to produce dump */ Dmsg0(500, "Done waitpid\n"); } else { Dmsg0(500, "Doing sleep\n"); bmicrosleep(30, 0); } if (WEXITSTATUS(chld_status) == 0) { fprintf(stderr, _("It looks like the traceback worked...\n")); } else { fprintf(stderr, _("The btraceback call returned %d\n"), WEXITSTATUS(chld_status)); } /* If we want it printed, do so */ #ifdef direct_print if (prt_kaboom) { FILE *fd; snprintf(buf, sizeof(buf), "%s/%s.%s.traceback", working_directory, my_name, pid_buf); fd = fopen(buf, "r"); if (fd != NULL) { printf("\n\n ==== Traceback output ====\n\n"); while (fgets(buf, (int)sizeof(buf), fd) != NULL) { printf("%s", buf); } fclose(fd); printf(" ==== End traceback output ====\n\n"); } } #else if (prt_kaboom) { snprintf(buf, sizeof(buf), "/bin/cat %s/%s.%s.traceback", working_directory, my_name, pid_buf); fprintf(stderr, "\n\n ==== Traceback output ====\n\n"); system(buf); fprintf(stderr, " ==== End traceback output ====\n\n"); } #endif #ifndef DEVELOPER /* When DEVELOPER set, this is done above */ /* print information about the current state into working/<file>.lockdump */ dbg_print_bacula(); #endif } #endif exit_handler(sig); Dmsg0(500, "Done exit_handler\n"); }