Alert and Warning are used in initialisation code, often
without any call to send_log. This assumes that stderr is
available which is currently the case. But when haproxy is
extended to be able to reinitialise it self such logging
may take place after haproxy is daemonised and thus detached
from the stderr. In order to make messages visible in
such situations Alert and Warning have been extended to also
log to send_log if possible.
---
 src/log.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/src/log.c b/src/log.c
index 333cbc6..119536c 100644
--- a/src/log.c
+++ b/src/log.c
@@ -54,27 +54,64 @@ const char *monthname[12] = {
 const char sess_term_cond[8]  = "-cCsSPRI";    /* normal, CliTo, CliErr, 
SrvTo, SrvErr, PxErr, Resource, Internal */
 const char sess_fin_state[8]  = "-RCHDLQT";    /* cliRequest, srvConnect, 
srvHeader, Data, Last, Queue, Tarpit */
 
+static void vsend_log(struct proxy *p, int level, const char *message,
+                     va_list argp);
+
 /*
- * Displays the message on stderr with the date and pid. Overrides the quiet
- * mode during startup.
+ * Displays the message on stderr with the date and pid.
+ * Also logs the same message using the prevailing logger, if any,
+ * with a priority of LOG_ERR.
+ * Overrides the quiet mode during startup.
+ *
+ * Internal function, do not call directly.
  */
-void Alert(const char *fmt, ...)
+static void __Alert(int send_log, const char *fmt, va_list argp)
 {
-       va_list argp;
        struct tm tm;
 
        if (!(global.mode & MODE_QUIET) || (global.mode & (MODE_VERBOSE | 
MODE_STARTING))) {
-               va_start(argp, fmt);
+               if (send_log) {
+                       va_list argp2;
+                       va_copy(argp2, argp);
+                       vsend_log(NULL, LOG_ERR, fmt, argp2);
+                       va_end(argp2);
+               }
 
                get_localtime(date.tv_sec, &tm);
                fprintf(stderr, "[ALERT] %03d/%02d%02d%02d (%d) : ",
                        tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec, 
(int)getpid());
                vfprintf(stderr, fmt, argp);
                fflush(stderr);
-               va_end(argp);
        }
 }
 
+/*
+ * Displays the message on stderr with the date and pid.
+ * Also logs the same message using the prevailing logger, if any,
+ * with a priority of LOG_ERR.
+ * Overrides the quiet mode during startup.
+ */
+void Alert(const char *fmt, ...)
+{
+       va_list argp;
+
+       va_start(argp, fmt);
+       __Alert(1, fmt, argp);
+       va_end(argp);
+}
+
+/*
+ * Displays the message on stderr with the date and pid. Overrides the quiet
+ * mode during startup.
+ */
+static void Alert_no_send_log(const char *fmt, ...)
+{
+       va_list argp;
+
+       va_start(argp, fmt);
+       __Alert(0, fmt, argp);
+       va_end(argp);
+}
 
 /*
  * Displays the message on stderr with the date and pid.
@@ -86,7 +123,10 @@ void Warning(const char *fmt, ...)
 
        if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
                va_start(argp, fmt);
+               vsend_log(NULL, LOG_WARNING, fmt, argp);
+               va_end(argp);
 
+               va_start(argp, fmt);
                get_localtime(date.tv_sec, &tm);
                fprintf(stderr, "[WARNING] %03d/%02d%02d%02d (%d) : ",
                        tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec, 
(int)getpid());
@@ -162,12 +202,12 @@ static inline int logsrv_addrlen(const struct logsrv 
*logsrv)
  * It also tries not to waste too much time computing the message header.
  * It doesn't care about errors nor does it report them.
  */
-void send_log(struct proxy *p, int level, const char *message, ...)
+static void vsend_log(struct proxy *p, int level, const char *message,
+                     va_list argp)
 {
        static int logfdunix = -1;      /* syslog to AF_UNIX socket */
        static int logfdinet = -1;      /* syslog to AF_INET socket */
        static long tvsec = -1; /* to force the string to be initialized */
-       va_list argp;
        static char logmsg[MAX_SYSLOG_LEN];
        static char *dataptr = NULL;
        int fac_level;
@@ -204,7 +244,6 @@ void send_log(struct proxy *p, int level, const char 
*message, ...)
                dataptr = logmsg + hdr_len;
        }
 
-       va_start(argp, message);
        /*
         * FIXME: we take a huge performance hit here. We might have to replace
         * vsnprintf() for a hard-coded log writer.
@@ -212,7 +251,6 @@ void send_log(struct proxy *p, int level, const char 
*message, ...)
        data_len = vsnprintf(dataptr, logmsg + sizeof(logmsg) - dataptr, 
message, argp);
        if (data_len < 0 || data_len > (logmsg + sizeof(logmsg) - dataptr))
                data_len = logmsg + sizeof(logmsg) - dataptr;
-       va_end(argp);
        dataptr[data_len - 1] = '\n'; /* force a break on ultra-long lines */
 
        if (p == NULL) {
@@ -266,8 +304,9 @@ void send_log(struct proxy *p, int level, const char 
*message, ...)
                }
                if ((*plogfd = socket(logsrv->u.addr.sa_family, SOCK_DGRAM,
                                proto)) < 0) {
-                       Alert("socket for logger #%d failed: %s (errno=%d)\n",
-                               nblogger + 1, strerror(errno), errno);
+                       Alert_no_send_log("socket for logger "
+                                         "#%d failed: %s (errno=%d)\n",
+                                         nblogger + 1, strerror(errno), errno);
                        return;
                }
                /* we don't want to receive anything on this socket */
@@ -307,12 +346,26 @@ void send_log(struct proxy *p, int level, const char 
*message, ...)
                sent = sendto(*plogfd, log_ptr, dataptr + data_len - log_ptr,
                        MSG_DONTWAIT | MSG_NOSIGNAL, &logsrv->u.addr, 
logsrv_addrlen(logsrv));
                if (sent < 0) {
-                       Alert("sendto logger #%d failed: %s (errno=%d)\n",
-                               nblogger, strerror(errno), errno);
+                       Alert_no_send_log("sendto logger #%d failed: "
+                                         "%s (errno=%d)\n",
+                                         nblogger, strerror(errno), errno);
                }
        }
 }
 
+/*
+ * This function sends a syslog message to both log servers of a proxy,
+ * or to global log servers if the proxy is NULL.
+ * It also tries not to waste too much time computing the message header.
+ * It doesn't care about errors nor does it report them.
+ */
+void send_log(struct proxy *p, int level, const char *message, ...)
+{
+       va_list argp;
+       va_start(argp, message);
+       vsend_log(p, level, message, argp);
+       va_end(argp);
+}
 
 /*
  * send a log for the session when we have enough info about it
-- 
1.7.2.3


Reply via email to