Module: check_mk
Branch: master
Commit: c5722db7dc535493213b709de8afed31a7387591
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=c5722db7dc5354…
Author: Mathias Kettner <mk(a)mathias-kettner.de>
Date: Mon Nov 14 13:24:26 2011 +0100
Livecheck: do not keep ICMP socket open
Because this is a massive performance problem. The
open socket will see all ICMP traffic coming an and buffer
that until we use it again.
---
livestatus/src/check_icmp.c | 3 +++
livestatus/src/livecheck.c | 12 +++++-------
livestatus/src/livechecking.c | 37 +++++++++++++++++++++++++++++--------
3 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/livestatus/src/check_icmp.c b/livestatus/src/check_icmp.c
index fd29a7c..9b0919c 100644
--- a/livestatus/src/check_icmp.c
+++ b/livestatus/src/check_icmp.c
@@ -384,8 +384,11 @@ int check_icmp(int argc, char **argv, char *output, int size)
g_output_buffer_size = size;
g_output_pointer = output;
+ icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
+
exit_code = 3;
if (setjmp(exit_jmp)) {
+ close(icmp_sock);
return exit_code;
}
diff --git a/livestatus/src/livecheck.c b/livestatus/src/livecheck.c
index 693c539..3af345c 100644
--- a/livestatus/src/livecheck.c
+++ b/livestatus/src/livecheck.c
@@ -66,12 +66,6 @@ int main(int argc, char **argv)
signal(SIGQUIT, term_handler);
signal(SIGTERM, term_handler);
- // Setup raw socket for inline check_icmp if we are root
- if (geteuid() == 0) {
- icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
- setuid(getuid()); /* Drop root priviledges */
- }
-
while (1) {
write(1, "*", 1); // Signal Nagios that we are finished
if (NULL == fgets(host, sizeof(host), stdin)
@@ -92,7 +86,7 @@ int main(int argc, char **argv)
// If it's check_icmp, we use our inline version
// of that. But only if we have (had) root priviledges
// and had been able to create a raw socket
- if (icmp_sock != -1 && strstr(command, "/check_icmp ")) {
+ if (geteuid() == 0 && strstr(command, "/check_icmp ")) {
char **arguments = parse_into_arguments(command);
int arg_c = 0;
while (arguments[arg_c])
@@ -106,6 +100,10 @@ int main(int argc, char **argv)
pid = fork();
if (pid == 0) {
+ // Drop root priviledges: only needed for ICMP socket
+ if (geteuid() == 0)
+ setuid(getuid());
+
close(fd[0]); // close read end
dup2(fd[1], 1); // point stdout into pipe
dup2(fd[1], 2); // also point stderr into pipe
diff --git a/livestatus/src/livechecking.c b/livestatus/src/livechecking.c
index 534132c..f4b2d42 100644
--- a/livestatus/src/livechecking.c
+++ b/livestatus/src/livechecking.c
@@ -46,6 +46,7 @@ struct live_helper {
pid_t pid;
int sock;
FILE *fsock;
+ int is_free;
};
struct live_helper *g_live_helpers;
@@ -65,10 +66,21 @@ void execute_livecheck(struct live_helper *lh, const char *host_name,
struct live_helper *get_free_live_helper()
{
- // Check if one of our helpers is free
+ // Check if one of our helpers is free. First look
+ // at the flag
+ unsigned i;
+ for (i=0; i<g_num_livehelpers; i++) {
+ if (g_live_helpers[i].is_free) {
+ g_live_helpers[i].is_free = 0;
+ return &g_live_helpers[i];
+ }
+ }
+
+ // None none to be free -> use select to detect livehelpers
+ // that have signalled us (by sending a byte) that they are
+ // free again.
fd_set fds;
FD_ZERO(&fds);
- unsigned i;
int max_fd = 0;
for (i=0; i<g_num_livehelpers; i++) {
int fd = g_live_helpers[i].sock;
@@ -83,11 +95,13 @@ struct live_helper *get_free_live_helper()
if (r == 0)
return 0;
+ struct live_helper *free_helper = 0;
for (i=0; i<g_num_livehelpers; i++) {
if (FD_ISSET(g_live_helpers[i].sock, &fds))
- break;
+ g_live_helpers[i].is_free = 1;
+ free_helper = &g_live_helpers[i];
}
- return &g_live_helpers[i];
+ return free_helper;
}
int broker_host_livecheck(int event_type __attribute__ ((__unused__)), void *data)
@@ -136,6 +150,7 @@ int broker_service_livecheck(int event_type __attribute__
((__unused__)), void *
struct live_helper *lh = get_free_live_helper();
if (!lh) {
logger(LG_INFO, "No livecheck helper free.");
+ // Let the core handle this check himself
return NEB_OK;
}
@@ -183,11 +198,11 @@ void init_livecheck()
snprintf(ht, sizeof(ht), "%u", host_check_timeout);
char st[32];
snprintf(st, sizeof(st), "%u", service_check_timeout);
+
// reduce stack size in order to save memory
struct rlimit rl;
getrlimit(RLIMIT_STACK, &rl);
- logger(LG_INFO, "Stacksize is %d", rl.rlim_cur);
- rl.rlim_cur = 32768;
+ rl.rlim_cur = 65536;
setrlimit(RLIMIT_STACK, &rl);
execl(g_livecheck_path, "livecheck", check_result_path, ht, st,
(char *)0);
logger(LG_INFO, "ERROR: Cannot start livecheck helper: %s",
strerror(errno));
@@ -197,6 +212,7 @@ void init_livecheck()
g_live_helpers[i].pid = pid;
g_live_helpers[i].sock = fd[0];
g_live_helpers[i].fsock = fdopen(fd[0], "r+");
+ g_live_helpers[i].is_free = 0; // wait until helper sends "ready"
byte.
}
}
@@ -212,8 +228,13 @@ void deinit_livecheck()
kill(g_live_helpers[i].pid, SIGTERM);
int status;
waitpid(g_live_helpers[i].pid, &status, 0);
- if (g_debug_level > 0)
- logger(LG_INFO, "Livecheck helper %d exited with status %d.",
g_live_helpers[i].pid, status);
+ if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM) {
+ logger(LG_INFO, "Livecheck helper %d exited with signal %d.",
+ g_live_helpers[i].pid, WTERMSIG(status));
+ }
+ else if (g_debug_level > 0)
+ logger(LG_INFO, "Livecheck helper %d exited with status %d.",
+ g_live_helpers[i].pid, status);
}
free(g_live_helpers);
}