1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
/*----------------------------------------------------------------------------*/
/* Xymon monitor library. */
/* */
/* This is a library module, part of libxymon. */
/* It contains routines for handling of signals and crashes. */
/* */
/* Copyright (C) 2002-2011 Henrik Storner <henrik@storner.dk> */
/* */
/* This program is released under the GNU General Public License (GPL), */
/* version 2. See the file "COPYING" for details. */
/* */
/*----------------------------------------------------------------------------*/
static char rcsid[] = "$Id: sig.c 8069 2019-07-23 15:29:06Z jccleaver $";
#include <limits.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include "libxymon.h"
/* Data used while crashing - cannot depend on the stack being usable */
static char signal_xymoncmd[PATH_MAX];
static char signal_xymondserver[1024];
static char signal_msg[1024];
static char signal_tmpdir[PATH_MAX];
static void sigsegv_handler(int signum)
{
/*
* This is a signal handler. Only a very limited number of
* library routines can be safely used here, according to
* Posix: http://www.opengroup.org/onlinepubs/007904975/functions/xsh_chap02_04.html#tag_02_04_03
* Do not use string, stdio etc. - just basic system calls.
* That is why we need to setup all of the strings in advance.
*/
signal(signum, SIG_DFL);
/*
* Try to fork a child to send in an alarm message.
* If the fork fails, then just attempt to exec() the XYMON command
*/
if (fork() <= 0) {
execl(signal_xymoncmd, "xymon-signal", signal_xymondserver, signal_msg, NULL);
}
/* Dump core and abort */
if (chdir(signal_tmpdir) == 0) {}; /* Cannot chdir? Well, abort anyway */
abort();
}
static void sigusr2_handler(int signum)
{
/* SIGUSR2 toggles debugging */
if (debug) {
dbgprintf("Debug OFF\n");
debug = 0;
}
else {
debug = 1;
dbgprintf("Debug ON\n");
}
}
void setup_signalhandler(char *programname)
{
struct rlimit lim;
struct sigaction sa;
MEMDEFINE(signal_xymoncmd);
MEMDEFINE(signal_xymondserver);
MEMDEFINE(signal_tmpdir);
MEMDEFINE(signal_msg);
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sigsegv_handler;
/*
* Try to allow ourselves to generate core files
*/
getrlimit(RLIMIT_CORE, &lim);
lim.rlim_cur = RLIM_INFINITY;
setrlimit(RLIMIT_CORE, &lim);
if (xgetenv("XYMON") == NULL) return;
if (xgetenv("XYMSRV") == NULL) return;
/*
* Used inside signal-handler. Must be setup in
* advance.
*/
strncpy(signal_xymoncmd, xgetenv("XYMON"), sizeof(signal_xymoncmd));
strncpy(signal_xymondserver, xgetenv("XYMSRV"), sizeof(signal_xymondserver));
strncpy(signal_tmpdir, xgetenv("XYMONTMP"), sizeof(signal_tmpdir));
snprintf(signal_msg, sizeof(signal_msg), "status %s.%s red - Program crashed\n\nFatal signal caught!\n",
(xgetenv("MACHINE") ? xgetenv("MACHINE") : "XYMSERVERS"), programname);
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGILL, &sa, NULL);
#ifdef SIGBUS
sigaction(SIGBUS, &sa, NULL);
#endif
/*
* After lengthy debugging and perusing of mail archives:
* Need to ignore SIGPIPE since FreeBSD (and others?) can throw this
* on a write() instead of simply returning -EPIPE like any sane
* OS would.
*/
signal(SIGPIPE, SIG_IGN);
/* Ignore SIGUSR1 unless explicitly set by main program */
signal (SIGUSR1, SIG_IGN);
/* SIGUSR2 toggles debugging */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sigusr2_handler;
sigaction(SIGUSR2, &sa, NULL);
}
|