summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Nierlein <sven@nierlein.de>2019-02-15 10:36:28 +0100
committerSven Nierlein <sven@nierlein.de>2019-02-15 10:36:28 +0100
commit7cafb0e84550035fe671662c293122be975065ca (patch)
tree5d80a8e80854edc41a72da668a89485505d7e5dc
parent2962148d8bac3a65f1fb5e1a948e3f0a86a42a1a (diff)
downloadmonitoring-plugins-7cafb0e84550035fe671662c293122be975065ca.tar.gz
check_by_ssh: fix child process leak on timeouts
When check_by_ssh runs into a timeout it simply exits keeping all child processes running. Simply adopting the kill loop from runcmd_timeout_alarm_handler() fixes this. Signed-off-by: Sven Nierlein <sven@nierlein.de>
-rw-r--r--lib/utils_base.c19
-rw-r--r--lib/utils_base.h5
-rw-r--r--lib/utils_cmd.c42
-rw-r--r--lib/utils_cmd.h13
-rw-r--r--plugins/check_dbi.c1
-rw-r--r--plugins/check_pgsql.c1
-rw-r--r--plugins/common.h14
-rw-r--r--plugins/popen.c29
-rw-r--r--plugins/runcmd.c13
-rw-r--r--plugins/utils.c31
-rw-r--r--plugins/utils.h9
11 files changed, 70 insertions, 107 deletions
diff --git a/lib/utils_base.c b/lib/utils_base.c
index 19a531f5..fd7058da 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -37,6 +37,9 @@
37 37
38monitoring_plugin *this_monitoring_plugin=NULL; 38monitoring_plugin *this_monitoring_plugin=NULL;
39 39
40unsigned int timeout_state = STATE_CRITICAL;
41unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
42
40int _np_state_read_file(FILE *); 43int _np_state_read_file(FILE *);
41 44
42void np_init( char *plugin_name, int argc, char **argv ) { 45void 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) {
359 return value; 362 return value;
360} 363}
361 364
365const char *
366state_text (int result)
367{
368 switch (result) {
369 case STATE_OK:
370 return "OK";
371 case STATE_WARNING:
372 return "WARNING";
373 case STATE_CRITICAL:
374 return "CRITICAL";
375 case STATE_DEPENDENT:
376 return "DEPENDENT";
377 default:
378 return "UNKNOWN";
379 }
380}
362 381
363/* 382/*
364 * Read a string representing a state (ok, warning... or numeric: 0, 1) and 383 * Read a string representing a state (ok, warning... or numeric: 0, 1) and
diff --git a/lib/utils_base.h b/lib/utils_base.h
index 42ae0c09..d7e7dffa 100644
--- a/lib/utils_base.h
+++ b/lib/utils_base.h
@@ -61,6 +61,10 @@ void print_thresholds(const char *, thresholds *);
61int check_range(double, range *); 61int check_range(double, range *);
62int get_status(double, thresholds *); 62int get_status(double, thresholds *);
63 63
64/* Handle timeouts */
65extern unsigned int timeout_state;
66extern unsigned int timeout_interval;
67
64/* All possible characters in a threshold range */ 68/* All possible characters in a threshold range */
65#define NP_THRESHOLDS_CHARS "-0123456789.:@~" 69#define NP_THRESHOLDS_CHARS "-0123456789.:@~"
66 70
@@ -107,5 +111,6 @@ void np_state_write_string(time_t, char *);
107void np_init(char *, int argc, char **argv); 111void np_init(char *, int argc, char **argv);
108void np_set_args(int argc, char **argv); 112void np_set_args(int argc, char **argv);
109void np_cleanup(); 113void np_cleanup();
114const char *state_text (int);
110 115
111#endif /* _UTILS_BASE_ */ 116#endif /* _UTILS_BASE_ */
diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c
index 7eb9a3a0..795840d3 100644
--- a/lib/utils_cmd.c
+++ b/lib/utils_cmd.c
@@ -40,6 +40,7 @@
40 40
41/** includes **/ 41/** includes **/
42#include "common.h" 42#include "common.h"
43#include "utils.h"
43#include "utils_cmd.h" 44#include "utils_cmd.h"
44#include "utils_base.h" 45#include "utils_base.h"
45#include <fcntl.h> 46#include <fcntl.h>
@@ -65,31 +66,6 @@ extern char **environ;
65# define SIG_ERR ((Sigfunc *)-1) 66# define SIG_ERR ((Sigfunc *)-1)
66#endif 67#endif
67 68
68/* This variable must be global, since there's no way the caller
69 * can forcibly slay a dead or ungainly running program otherwise.
70 * Multithreading apps and plugins can initialize it (via CMD_INIT)
71 * in an async safe manner PRIOR to calling cmd_run() or cmd_run_array()
72 * for the first time.
73 *
74 * The check for initialized values is atomic and can
75 * occur in any number of threads simultaneously. */
76static pid_t *_cmd_pids = NULL;
77
78/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
79 * If that fails and the macro isn't defined, we fall back to an educated
80 * guess. There's no guarantee that our guess is adequate and the program
81 * will die with SIGSEGV if it isn't and the upper boundary is breached. */
82#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */
83#define MAXFD_LIMIT 8192 /* upper limit of open files */
84#ifdef _SC_OPEN_MAX
85static long maxfd = 0;
86#elif defined(OPEN_MAX)
87# define maxfd OPEN_MAX
88#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
89# define maxfd DEFAULT_MAXFD
90#endif
91
92
93/** prototypes **/ 69/** prototypes **/
94static int _cmd_open (char *const *, int *, int *) 70static int _cmd_open (char *const *, int *, int *)
95 __attribute__ ((__nonnull__ (1, 2, 3))); 71 __attribute__ ((__nonnull__ (1, 2, 3)));
@@ -406,3 +382,19 @@ cmd_file_read ( char *filename, output *out, int flags)
406 382
407 return 0; 383 return 0;
408} 384}
385
386void
387timeout_alarm_handler (int signo)
388{
389 size_t i;
390 if (signo == SIGALRM) {
391 printf (_("%s - Plugin timed out after %d seconds\n"),
392 state_text(timeout_state), timeout_interval);
393
394 if(_cmd_pids) for(i = 0; i < maxfd; i++) {
395 if(_cmd_pids[i] != 0) kill(_cmd_pids[i], SIGKILL);
396 }
397
398 exit (timeout_state);
399 }
400}
diff --git a/lib/utils_cmd.h b/lib/utils_cmd.h
index ebaf15be..6f3aeb81 100644
--- a/lib/utils_cmd.h
+++ b/lib/utils_cmd.h
@@ -32,4 +32,17 @@ void cmd_init (void);
32#define CMD_NO_ARRAYS 0x01 /* don't populate arrays at all */ 32#define CMD_NO_ARRAYS 0x01 /* don't populate arrays at all */
33#define CMD_NO_ASSOC 0x02 /* output.line won't point to buf */ 33#define CMD_NO_ASSOC 0x02 /* output.line won't point to buf */
34 34
35/* This variable must be global, since there's no way the caller
36 * can forcibly slay a dead or ungainly running program otherwise.
37 * Multithreading apps and plugins can initialize it (via CMD_INIT)
38 * in an async safe manner PRIOR to calling cmd_run() or cmd_run_array()
39 * for the first time.
40 *
41 * The check for initialized values is atomic and can
42 * occur in any number of threads simultaneously. */
43static pid_t *_cmd_pids = NULL;
44
45RETSIGTYPE timeout_alarm_handler (int);
46
47
35#endif /* _UTILS_CMD_ */ 48#endif /* _UTILS_CMD_ */
diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c
index 826eb8d9..ced13d05 100644
--- a/plugins/check_dbi.c
+++ b/plugins/check_dbi.c
@@ -35,6 +35,7 @@ const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
37#include "utils.h" 37#include "utils.h"
38#include "utils_cmd.h"
38 39
39#include "netutils.h" 40#include "netutils.h"
40 41
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index 5cd47093..11ce6916 100644
--- a/plugins/check_pgsql.c
+++ b/plugins/check_pgsql.c
@@ -34,6 +34,7 @@ const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
36#include "utils.h" 36#include "utils.h"
37#include "utils_cmd.h"
37 38
38#include "netutils.h" 39#include "netutils.h"
39#include <libpq-fe.h> 40#include <libpq-fe.h>
diff --git a/plugins/common.h b/plugins/common.h
index 6bf4fca4..0f08e2f6 100644
--- a/plugins/common.h
+++ b/plugins/common.h
@@ -225,4 +225,18 @@ enum {
225# define __attribute__(x) /* do nothing */ 225# define __attribute__(x) /* do nothing */
226#endif 226#endif
227 227
228/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
229 * If that fails and the macro isn't defined, we fall back to an educated
230 * guess. There's no guarantee that our guess is adequate and the program
231 * will die with SIGSEGV if it isn't and the upper boundary is breached. */
232#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */
233#define MAXFD_LIMIT 8192 /* upper limit of open files */
234#ifdef _SC_OPEN_MAX
235static long maxfd = 0;
236#elif defined(OPEN_MAX)
237# define maxfd OPEN_MAX
238#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
239# define maxfd DEFAULT_MAXFD
240#endif
241
228#endif /* _COMMON_H_ */ 242#endif /* _COMMON_H_ */
diff --git a/plugins/popen.c b/plugins/popen.c
index 592263fd..116d168d 100644
--- a/plugins/popen.c
+++ b/plugins/popen.c
@@ -78,7 +78,6 @@ RETSIGTYPE popen_timeout_alarm_handler (int);
78 78
79#define min(a,b) ((a) < (b) ? (a) : (b)) 79#define min(a,b) ((a) < (b) ? (a) : (b))
80#define max(a,b) ((a) > (b) ? (a) : (b)) 80#define max(a,b) ((a) > (b) ? (a) : (b))
81int open_max (void); /* {Prog openmax} */
82static void err_sys (const char *, ...) __attribute__((noreturn,format(printf, 1, 2))); 81static void err_sys (const char *, ...) __attribute__((noreturn,format(printf, 1, 2)));
83char *rtrim (char *, const char *); 82char *rtrim (char *, const char *);
84 83
@@ -86,7 +85,6 @@ char *pname = NULL; /* caller can set this from argv[0] */
86 85
87/*int *childerr = NULL;*//* ptr to array allocated at run-time */ 86/*int *childerr = NULL;*//* ptr to array allocated at run-time */
88/*extern pid_t *childpid = NULL; *//* ptr to array allocated at run-time */ 87/*extern pid_t *childpid = NULL; *//* ptr to array allocated at run-time */
89static int maxfd; /* from our open_max(), {Prog openmax} */
90 88
91#ifdef REDHAT_SPOPEN_ERROR 89#ifdef REDHAT_SPOPEN_ERROR
92static volatile int childtermd = 0; 90static volatile int childtermd = 0;
@@ -187,13 +185,11 @@ spopen (const char *cmdstring)
187 argv[i] = NULL; 185 argv[i] = NULL;
188 186
189 if (childpid == NULL) { /* first time through */ 187 if (childpid == NULL) { /* first time through */
190 maxfd = open_max (); /* allocate zeroed out array for child pids */
191 if ((childpid = calloc ((size_t)maxfd, sizeof (pid_t))) == NULL) 188 if ((childpid = calloc ((size_t)maxfd, sizeof (pid_t))) == NULL)
192 return (NULL); 189 return (NULL);
193 } 190 }
194 191
195 if (child_stderr_array == NULL) { /* first time through */ 192 if (child_stderr_array == NULL) { /* first time through */
196 maxfd = open_max (); /* allocate zeroed out array for child pids */
197 if ((child_stderr_array = calloc ((size_t)maxfd, sizeof (int))) == NULL) 193 if ((child_stderr_array = calloc ((size_t)maxfd, sizeof (int))) == NULL)
198 return (NULL); 194 return (NULL);
199 } 195 }
@@ -273,15 +269,6 @@ spclose (FILE * fp)
273 return (1); 269 return (1);
274} 270}
275 271
276#ifdef OPEN_MAX
277static int openmax = OPEN_MAX;
278#else
279static int openmax = 0;
280#endif
281
282#define OPEN_MAX_GUESS 256 /* if OPEN_MAX is indeterminate */
283 /* no guarantee this is adequate */
284
285#ifdef REDHAT_SPOPEN_ERROR 272#ifdef REDHAT_SPOPEN_ERROR
286RETSIGTYPE 273RETSIGTYPE
287popen_sigchld_handler (int signo) 274popen_sigchld_handler (int signo)
@@ -311,22 +298,6 @@ popen_timeout_alarm_handler (int signo)
311} 298}
312 299
313 300
314int
315open_max (void)
316{
317 if (openmax == 0) { /* first time through */
318 errno = 0;
319 if ((openmax = sysconf (_SC_OPEN_MAX)) < 0) {
320 if (errno == 0)
321 openmax = OPEN_MAX_GUESS; /* it's indeterminate */
322 else
323 err_sys (_("sysconf error for _SC_OPEN_MAX"));
324 }
325 }
326 return (openmax);
327}
328
329
330/* Fatal error related to a system call. 301/* Fatal error related to a system call.
331 * Print a message and die. */ 302 * Print a message and die. */
332 303
diff --git a/plugins/runcmd.c b/plugins/runcmd.c
index 1a7c904f..c3828678 100644
--- a/plugins/runcmd.c
+++ b/plugins/runcmd.c
@@ -67,19 +67,6 @@
67 * occur in any number of threads simultaneously. */ 67 * occur in any number of threads simultaneously. */
68static pid_t *np_pids = NULL; 68static pid_t *np_pids = NULL;
69 69
70/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
71 * If that fails and the macro isn't defined, we fall back to an educated
72 * guess. There's no guarantee that our guess is adequate and the program
73 * will die with SIGSEGV if it isn't and the upper boundary is breached. */
74#ifdef _SC_OPEN_MAX
75static long maxfd = 0;
76#elif defined(OPEN_MAX)
77# define maxfd OPEN_MAX
78#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
79# define maxfd 256
80#endif
81
82
83/** prototypes **/ 70/** prototypes **/
84static int np_runcmd_open(const char *, int *, int *) 71static int np_runcmd_open(const char *, int *, int *)
85 __attribute__((__nonnull__(1, 2, 3))); 72 __attribute__((__nonnull__(1, 2, 3)));
diff --git a/plugins/utils.c b/plugins/utils.c
index 231af92b..ee620133 100644
--- a/plugins/utils.c
+++ b/plugins/utils.c
@@ -36,9 +36,6 @@ extern const char *progname;
36#define STRLEN 64 36#define STRLEN 64
37#define TXTBLK 128 37#define TXTBLK 128
38 38
39unsigned int timeout_state = STATE_CRITICAL;
40unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
41
42time_t start_time, end_time; 39time_t start_time, end_time;
43 40
44/* ************************************************************************** 41/* **************************************************************************
@@ -148,33 +145,6 @@ print_revision (const char *command_name, const char *revision)
148 command_name, revision, PACKAGE, VERSION); 145 command_name, revision, PACKAGE, VERSION);
149} 146}
150 147
151const char *
152state_text (int result)
153{
154 switch (result) {
155 case STATE_OK:
156 return "OK";
157 case STATE_WARNING:
158 return "WARNING";
159 case STATE_CRITICAL:
160 return "CRITICAL";
161 case STATE_DEPENDENT:
162 return "DEPENDENT";
163 default:
164 return "UNKNOWN";
165 }
166}
167
168void
169timeout_alarm_handler (int signo)
170{
171 if (signo == SIGALRM) {
172 printf (_("%s - Plugin timed out after %d seconds\n"),
173 state_text(timeout_state), timeout_interval);
174 exit (timeout_state);
175 }
176}
177
178int 148int
179is_numeric (char *number) 149is_numeric (char *number)
180{ 150{
@@ -708,4 +678,3 @@ char *sperfdata_int (const char *label,
708 678
709 return data; 679 return data;
710} 680}
711
diff --git a/plugins/utils.h b/plugins/utils.h
index a436e1ca..6aa316fe 100644
--- a/plugins/utils.h
+++ b/plugins/utils.h
@@ -29,13 +29,6 @@ suite of plugins. */
29void support (void); 29void support (void);
30void print_revision (const char *, const char *); 30void print_revision (const char *, const char *);
31 31
32/* Handle timeouts */
33
34extern unsigned int timeout_state;
35extern unsigned int timeout_interval;
36
37RETSIGTYPE timeout_alarm_handler (int);
38
39extern time_t start_time, end_time; 32extern time_t start_time, end_time;
40 33
41/* Test input types */ 34/* Test input types */
@@ -89,8 +82,6 @@ void usage4(const char *) __attribute__((noreturn));
89void usage5(void) __attribute__((noreturn)); 82void usage5(void) __attribute__((noreturn));
90void usage_va(const char *fmt, ...) __attribute__((noreturn)); 83void usage_va(const char *fmt, ...) __attribute__((noreturn));
91 84
92const char *state_text (int);
93
94#define max(a,b) (((a)>(b))?(a):(b)) 85#define max(a,b) (((a)>(b))?(a):(b))
95#define min(a,b) (((a)<(b))?(a):(b)) 86#define min(a,b) (((a)<(b))?(a):(b))
96 87