mirror of
https://github.com/monitoring-plugins/monitoring-plugins.git
synced 2026-04-28 09:36:56 -04:00
Merge pull request #1583 from sni/fix_check_by_ssh_timeout_child_leak
check_by_ssh: fix child process leak on timeouts
This commit is contained in:
commit
931ed78b5d
11 changed files with 70 additions and 107 deletions
|
|
@ -37,6 +37,9 @@
|
|||
|
||||
monitoring_plugin *this_monitoring_plugin=NULL;
|
||||
|
||||
unsigned int timeout_state = STATE_CRITICAL;
|
||||
unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
|
||||
|
||||
int _np_state_read_file(FILE *);
|
||||
|
||||
void np_init( char *plugin_name, int argc, char **argv ) {
|
||||
|
|
@ -359,6 +362,22 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
|
|||
return value;
|
||||
}
|
||||
|
||||
const char *
|
||||
state_text (int result)
|
||||
{
|
||||
switch (result) {
|
||||
case STATE_OK:
|
||||
return "OK";
|
||||
case STATE_WARNING:
|
||||
return "WARNING";
|
||||
case STATE_CRITICAL:
|
||||
return "CRITICAL";
|
||||
case STATE_DEPENDENT:
|
||||
return "DEPENDENT";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a string representing a state (ok, warning... or numeric: 0, 1) and
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ void print_thresholds(const char *, thresholds *);
|
|||
int check_range(double, range *);
|
||||
int get_status(double, thresholds *);
|
||||
|
||||
/* Handle timeouts */
|
||||
extern unsigned int timeout_state;
|
||||
extern unsigned int timeout_interval;
|
||||
|
||||
/* All possible characters in a threshold range */
|
||||
#define NP_THRESHOLDS_CHARS "-0123456789.:@~"
|
||||
|
||||
|
|
@ -107,5 +111,6 @@ void np_state_write_string(time_t, char *);
|
|||
void np_init(char *, int argc, char **argv);
|
||||
void np_set_args(int argc, char **argv);
|
||||
void np_cleanup();
|
||||
const char *state_text (int);
|
||||
|
||||
#endif /* _UTILS_BASE_ */
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
/** includes **/
|
||||
#include "common.h"
|
||||
#include "utils.h"
|
||||
#include "utils_cmd.h"
|
||||
#include "utils_base.h"
|
||||
#include <fcntl.h>
|
||||
|
|
@ -65,31 +66,6 @@ extern char **environ;
|
|||
# define SIG_ERR ((Sigfunc *)-1)
|
||||
#endif
|
||||
|
||||
/* This variable must be global, since there's no way the caller
|
||||
* can forcibly slay a dead or ungainly running program otherwise.
|
||||
* Multithreading apps and plugins can initialize it (via CMD_INIT)
|
||||
* in an async safe manner PRIOR to calling cmd_run() or cmd_run_array()
|
||||
* for the first time.
|
||||
*
|
||||
* The check for initialized values is atomic and can
|
||||
* occur in any number of threads simultaneously. */
|
||||
static pid_t *_cmd_pids = NULL;
|
||||
|
||||
/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
|
||||
* If that fails and the macro isn't defined, we fall back to an educated
|
||||
* guess. There's no guarantee that our guess is adequate and the program
|
||||
* will die with SIGSEGV if it isn't and the upper boundary is breached. */
|
||||
#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */
|
||||
#define MAXFD_LIMIT 8192 /* upper limit of open files */
|
||||
#ifdef _SC_OPEN_MAX
|
||||
static long maxfd = 0;
|
||||
#elif defined(OPEN_MAX)
|
||||
# define maxfd OPEN_MAX
|
||||
#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
|
||||
# define maxfd DEFAULT_MAXFD
|
||||
#endif
|
||||
|
||||
|
||||
/** prototypes **/
|
||||
static int _cmd_open (char *const *, int *, int *)
|
||||
__attribute__ ((__nonnull__ (1, 2, 3)));
|
||||
|
|
@ -406,3 +382,19 @@ cmd_file_read ( char *filename, output *out, int flags)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
timeout_alarm_handler (int signo)
|
||||
{
|
||||
size_t i;
|
||||
if (signo == SIGALRM) {
|
||||
printf (_("%s - Plugin timed out after %d seconds\n"),
|
||||
state_text(timeout_state), timeout_interval);
|
||||
|
||||
if(_cmd_pids) for(i = 0; i < maxfd; i++) {
|
||||
if(_cmd_pids[i] != 0) kill(_cmd_pids[i], SIGKILL);
|
||||
}
|
||||
|
||||
exit (timeout_state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,4 +32,17 @@ void cmd_init (void);
|
|||
#define CMD_NO_ARRAYS 0x01 /* don't populate arrays at all */
|
||||
#define CMD_NO_ASSOC 0x02 /* output.line won't point to buf */
|
||||
|
||||
/* This variable must be global, since there's no way the caller
|
||||
* can forcibly slay a dead or ungainly running program otherwise.
|
||||
* Multithreading apps and plugins can initialize it (via CMD_INIT)
|
||||
* in an async safe manner PRIOR to calling cmd_run() or cmd_run_array()
|
||||
* for the first time.
|
||||
*
|
||||
* The check for initialized values is atomic and can
|
||||
* occur in any number of threads simultaneously. */
|
||||
static pid_t *_cmd_pids = NULL;
|
||||
|
||||
RETSIGTYPE timeout_alarm_handler (int);
|
||||
|
||||
|
||||
#endif /* _UTILS_CMD_ */
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ const char *email = "devel@monitoring-plugins.org";
|
|||
|
||||
#include "common.h"
|
||||
#include "utils.h"
|
||||
#include "utils_cmd.h"
|
||||
|
||||
#include "netutils.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ const char *email = "devel@monitoring-plugins.org";
|
|||
|
||||
#include "common.h"
|
||||
#include "utils.h"
|
||||
#include "utils_cmd.h"
|
||||
|
||||
#include "netutils.h"
|
||||
#include <libpq-fe.h>
|
||||
|
|
|
|||
|
|
@ -225,4 +225,18 @@ enum {
|
|||
# define __attribute__(x) /* do nothing */
|
||||
#endif
|
||||
|
||||
/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
|
||||
* If that fails and the macro isn't defined, we fall back to an educated
|
||||
* guess. There's no guarantee that our guess is adequate and the program
|
||||
* will die with SIGSEGV if it isn't and the upper boundary is breached. */
|
||||
#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */
|
||||
#define MAXFD_LIMIT 8192 /* upper limit of open files */
|
||||
#ifdef _SC_OPEN_MAX
|
||||
static long maxfd = 0;
|
||||
#elif defined(OPEN_MAX)
|
||||
# define maxfd OPEN_MAX
|
||||
#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
|
||||
# define maxfd DEFAULT_MAXFD
|
||||
#endif
|
||||
|
||||
#endif /* _COMMON_H_ */
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ RETSIGTYPE popen_timeout_alarm_handler (int);
|
|||
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
int open_max (void); /* {Prog openmax} */
|
||||
static void err_sys (const char *, ...) __attribute__((noreturn,format(printf, 1, 2)));
|
||||
char *rtrim (char *, const char *);
|
||||
|
||||
|
|
@ -86,7 +85,6 @@ char *pname = NULL; /* caller can set this from argv[0] */
|
|||
|
||||
/*int *childerr = NULL;*//* ptr to array allocated at run-time */
|
||||
/*extern pid_t *childpid = NULL; *//* ptr to array allocated at run-time */
|
||||
static int maxfd; /* from our open_max(), {Prog openmax} */
|
||||
|
||||
#ifdef REDHAT_SPOPEN_ERROR
|
||||
static volatile int childtermd = 0;
|
||||
|
|
@ -187,13 +185,11 @@ spopen (const char *cmdstring)
|
|||
argv[i] = NULL;
|
||||
|
||||
if (childpid == NULL) { /* first time through */
|
||||
maxfd = open_max (); /* allocate zeroed out array for child pids */
|
||||
if ((childpid = calloc ((size_t)maxfd, sizeof (pid_t))) == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (child_stderr_array == NULL) { /* first time through */
|
||||
maxfd = open_max (); /* allocate zeroed out array for child pids */
|
||||
if ((child_stderr_array = calloc ((size_t)maxfd, sizeof (int))) == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
|
|
@ -273,15 +269,6 @@ spclose (FILE * fp)
|
|||
return (1);
|
||||
}
|
||||
|
||||
#ifdef OPEN_MAX
|
||||
static int openmax = OPEN_MAX;
|
||||
#else
|
||||
static int openmax = 0;
|
||||
#endif
|
||||
|
||||
#define OPEN_MAX_GUESS 256 /* if OPEN_MAX is indeterminate */
|
||||
/* no guarantee this is adequate */
|
||||
|
||||
#ifdef REDHAT_SPOPEN_ERROR
|
||||
RETSIGTYPE
|
||||
popen_sigchld_handler (int signo)
|
||||
|
|
@ -311,22 +298,6 @@ popen_timeout_alarm_handler (int signo)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
open_max (void)
|
||||
{
|
||||
if (openmax == 0) { /* first time through */
|
||||
errno = 0;
|
||||
if ((openmax = sysconf (_SC_OPEN_MAX)) < 0) {
|
||||
if (errno == 0)
|
||||
openmax = OPEN_MAX_GUESS; /* it's indeterminate */
|
||||
else
|
||||
err_sys (_("sysconf error for _SC_OPEN_MAX"));
|
||||
}
|
||||
}
|
||||
return (openmax);
|
||||
}
|
||||
|
||||
|
||||
/* Fatal error related to a system call.
|
||||
* Print a message and die. */
|
||||
|
||||
|
|
|
|||
|
|
@ -67,19 +67,6 @@
|
|||
* occur in any number of threads simultaneously. */
|
||||
static pid_t *np_pids = NULL;
|
||||
|
||||
/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
|
||||
* If that fails and the macro isn't defined, we fall back to an educated
|
||||
* guess. There's no guarantee that our guess is adequate and the program
|
||||
* will die with SIGSEGV if it isn't and the upper boundary is breached. */
|
||||
#ifdef _SC_OPEN_MAX
|
||||
static long maxfd = 0;
|
||||
#elif defined(OPEN_MAX)
|
||||
# define maxfd OPEN_MAX
|
||||
#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
|
||||
# define maxfd 256
|
||||
#endif
|
||||
|
||||
|
||||
/** prototypes **/
|
||||
static int np_runcmd_open(const char *, int *, int *)
|
||||
__attribute__((__nonnull__(1, 2, 3)));
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ extern const char *progname;
|
|||
#define STRLEN 64
|
||||
#define TXTBLK 128
|
||||
|
||||
unsigned int timeout_state = STATE_CRITICAL;
|
||||
unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
|
||||
|
||||
time_t start_time, end_time;
|
||||
|
||||
/* **************************************************************************
|
||||
|
|
@ -148,33 +145,6 @@ print_revision (const char *command_name, const char *revision)
|
|||
command_name, revision, PACKAGE, VERSION);
|
||||
}
|
||||
|
||||
const char *
|
||||
state_text (int result)
|
||||
{
|
||||
switch (result) {
|
||||
case STATE_OK:
|
||||
return "OK";
|
||||
case STATE_WARNING:
|
||||
return "WARNING";
|
||||
case STATE_CRITICAL:
|
||||
return "CRITICAL";
|
||||
case STATE_DEPENDENT:
|
||||
return "DEPENDENT";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
timeout_alarm_handler (int signo)
|
||||
{
|
||||
if (signo == SIGALRM) {
|
||||
printf (_("%s - Plugin timed out after %d seconds\n"),
|
||||
state_text(timeout_state), timeout_interval);
|
||||
exit (timeout_state);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
is_numeric (char *number)
|
||||
{
|
||||
|
|
@ -708,4 +678,3 @@ char *sperfdata_int (const char *label,
|
|||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,13 +29,6 @@ suite of plugins. */
|
|||
void support (void);
|
||||
void print_revision (const char *, const char *);
|
||||
|
||||
/* Handle timeouts */
|
||||
|
||||
extern unsigned int timeout_state;
|
||||
extern unsigned int timeout_interval;
|
||||
|
||||
RETSIGTYPE timeout_alarm_handler (int);
|
||||
|
||||
extern time_t start_time, end_time;
|
||||
|
||||
/* Test input types */
|
||||
|
|
@ -89,8 +82,6 @@ void usage4(const char *) __attribute__((noreturn));
|
|||
void usage5(void) __attribute__((noreturn));
|
||||
void usage_va(const char *fmt, ...) __attribute__((noreturn));
|
||||
|
||||
const char *state_text (int);
|
||||
|
||||
#define max(a,b) (((a)>(b))?(a):(b))
|
||||
#define min(a,b) (((a)<(b))?(a):(b))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue