Hello,

I use a "check host" statement in which multiple ports are monitored. The
alerts are passed on to an external script which uses the environment
variables that monit sets. In some cases where multiple "failed" and
"succeeded" events are raised, the value for MONIT_DESCRIPTION is
wrong, namely that of a different event. The existing code always seems
to use Event_get_message() for the first entry in the eventlist, even if
the event itself is not the first on that list.

The attached patch fixes this for me, although it is quiet invasive as
it modifies the "spawn" prototype. Perhaps someone sees a more elegant
solution?

The patch is against SVN revision 205 on "trunk".

Here is an example snippet for monitrc to illustrate the situation:

check host appserver with address 192.168.1.1
        start program = "/home/marco/bin/appserver --workdir 
/home/marco/testsuite/appserver --daemon"
        stop program = "/home/marco/bin/appserver --workdir 
/home/marco/testsuite/appserver --quit"
    if failed port 9080 protocol http with timeout 5 seconds
        then exec "/home/marco/src/test-monit/bin/my_alert 'Failed for port 
9080'"
        else if succeeded then exec "/home/marco/src/test-monit/bin/my_alert 
'Succeeded for port 9080'"
    if failed port 9081 protocol http with timeout 5 seconds
        then exec "/home/marco/src/test-monit/bin/my_alert 'Failed for port 
9081'"
        else if succeeded then exec "/home/marco/src/test-monit/bin/my_alert 
'Succeeded for port 9081'"
    if failed port 9082 protocol http with timeout 5 seconds
        then exec "/home/marco/src/test-monit/bin/my_alert 'Failed for port 
9082'"
        else if succeeded then exec "/home/marco/src/test-monit/bin/my_alert 
'Succeeded for port 9082'"

If say ports 9080 and 9081 fail for some time, and then 9080 is again
available you might get the following entries in the call of my_alert for port 
9081:

MONIT_DESCRIPTION=connection succeeded to INET[192.168.1.1:9080] via TCP
MONIT_EVENT=Connection failed
argv[1]='Failed for port 9081'

Note that this "bug" (if that's what it is) only manifests itself in the
setting of MONIT_DESCRIPTION when an external program is called, and can
be worked around by using multiple "check host" statements.
-- 
Marco Roeland
commit 7f35086c2027400f9f5262a49fc8b79006e37781
Author: Marco Roeland <marco.roel...@xs4all.nl>
Date:   Fri Jul 23 11:09:54 2010 +0200

    Pass correct MONIT_DESCRIPTION env variable for external program
    
    In case of multiple simultaneous events for a service the value passed to
    external programs for MONIT_DESCRIPTION was that for the first encountered
    event and so not always the value for the correct event.
    
    Fix this by passing the event in the spawn function call.

diff --git a/control.c b/control.c
index 5514363..bfa1479 100644
--- a/control.c
+++ b/control.c
@@ -334,7 +334,7 @@ static void do_start(Service_T s) {
   
   if (s->start && (s->type!=TYPE_PROCESS || !Util_isProcessRunning(s))) {
     LogInfo("'%s' start: %s\n", s->name, s->start->arg[0]);
-    spawn(s, s->start, "Started");
+    spawn(s, s->start, NULL, "Started");
     /* We only wait for a process type, other service types does not have a 
pid file to watch */
     if (s->type == TYPE_PROCESS)
       wait_start(s);
@@ -364,7 +364,7 @@ static int do_stop(Service_T s) {
 
   if (s->stop && (s->type!=TYPE_PROCESS || Util_isProcessRunning(s))) {
     LogInfo("'%s' stop: %s\n", s->name, s->stop->arg[0]);
-    spawn(s, s->stop, "Stopped");
+    spawn(s, s->stop, NULL, "Stopped");
     if (s->type == TYPE_PROCESS) {
       /* Only wait for process service types */
       if (!wait_stop(s))
diff --git a/event.c b/event.c
index 9620c07..e60a1f5 100644
--- a/event.c
+++ b/event.c
@@ -709,7 +709,7 @@ static void handle_action(Event_T E, Action_T A) {
     return;
   } else if (A->id == ACTION_EXEC) {
     LogInfo("'%s' exec: %s\n", s->name, A->exec->arg[0]);
-    spawn(s, A->exec, Event_get_description(E));
+    spawn(s, A->exec, E, Event_get_description(E));
     return;
   } else {
     if (s->actionratelist && (A->id == ACTION_START || A->id == 
ACTION_RESTART))
diff --git a/monitor.h b/monitor.h
index 62cea95..4523019 100644
--- a/monitor.h
+++ b/monitor.h
@@ -905,7 +905,7 @@ int   control_service_string(const char *, const char *);
 int   control_service_daemon(const char *, const char *);
 void  setup_dependants();
 void  reset_depend();
-void  spawn(Service_T, Command_T, const char *);
+void  spawn(Service_T, Command_T, Event_T, const char *);
 int   status(char *);
 int   log_init();
 void  LogEmergency(const char *, ...);
diff --git a/spawn.c b/spawn.c
index b8a4945..f3fb01c 100644
--- a/spawn.c
+++ b/spawn.c
@@ -114,7 +114,7 @@ typedef struct En {
 static void put_monit_environment(Environment_T e);
 static void free_monit_environment(Environment_T *e);
 static void push_monit_environment(const char *env, Environment_T *list);
-static void set_monit_environment(Service_T s, const char *event, 
Environment_T *e);
+static void set_monit_environment(Service_T s, Event_T E, const char *event, 
Environment_T *e);
 
 
 /* ------------------------------------------------------------------ Public */
@@ -128,7 +128,7 @@ static void set_monit_environment(Service_T s, const char 
*event, Environment_T
  * @param E An optional event string, specifying why this function was
  * called. May be NULL.
  */
-void spawn(Service_T S, Command_T C, const char *E) {
+void spawn(Service_T S, Command_T C, Event_T E, const char *event) {
 
   pid_t pid;
   sigset_t mask;
@@ -152,7 +152,7 @@ void spawn(Service_T S, Command_T C, const char *E) {
   sigaddset(&mask, SIGCHLD);
   pthread_sigmask(SIG_BLOCK, &mask, &save);
 
-  set_monit_environment(S, E, &environment);
+  set_monit_environment(S, E, event, &environment);
 
   pid= fork();
   if(pid < 0) {
@@ -260,6 +260,7 @@ void spawn(Service_T S, Command_T C, const char *E) {
  * executed may use such variable for various purposes.
  */
 static void set_monit_environment(Service_T s, 
+                                 Event_T E, 
                                  const char *event, 
                                  Environment_T *e) {
   
@@ -281,7 +282,7 @@ static void set_monit_environment(Service_T s,
   push_monit_environment(buf, e);
   
   if (s->eventlist) {
-    snprintf(buf, STRLEN, "MONIT_DESCRIPTION=%s", s->eventlist->message);
+    snprintf(buf, STRLEN, "MONIT_DESCRIPTION=%s", E ? Event_get_message(E) : 
s->eventlist->message);
     push_monit_environment(buf, e);
   }
 
_______________________________________________
monit-dev mailing list
monit-dev@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monit-dev

Reply via email to