Author: aconway
Date: Wed Dec 10 22:17:29 2014
New Revision: 1644532

URL: http://svn.apache.org/r1644532
Log:
DISPATCH-83: Error messages are not displayed if an error occurs when starting 
in deamon mode.

Examples:

$ qdrouterd -d -U xx
Daemon error: Can't look up user xx
$ qdrouterd -d -I xx
Daemon error: Cannot stat python library path 'xx'
$ qdrouterd -d -c xx
Daemon error: Exception: Cannot load configuration file xx: [Errno 2] No such 
file or directory: 'xx'
$ qdrouterd -d -P /xx
Daemon error: Can't write pidfile /xx

Modified:
    qpid/dispatch/trunk/include/qpid/dispatch/error.h
    qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py
    qpid/dispatch/trunk/router/src/main.c
    qpid/dispatch/trunk/src/error.c

Modified: qpid/dispatch/trunk/include/qpid/dispatch/error.h
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/include/qpid/dispatch/error.h?rev=1644532&r1=1644531&r2=1644532&view=diff
==============================================================================
--- qpid/dispatch/trunk/include/qpid/dispatch/error.h (original)
+++ qpid/dispatch/trunk/include/qpid/dispatch/error.h Wed Dec 10 22:17:29 2014
@@ -46,7 +46,8 @@ typedef enum {
     QD_ERROR_CONFIG,            ///< Error in configuration
     QD_ERROR_TYPE,              ///< Value of inappropriate type.
     QD_ERROR_VALUE,             ///< Invalid value.
-    QD_ERROR_RUNTIME            ///< Run-time failure.
+    QD_ERROR_RUNTIME,           ///< Run-time failure.
+    QD_ERROR_SYSTEM             ///< System error from errno
 } qd_error_t;
 ENUM_DECLARE(qd_error);
 
@@ -62,8 +63,9 @@ qd_error_t qd_error_impl(qd_error_t code
 
 /**
  * Clear thread-local error code and message.
+ *@return QD_ERROR_NONE
  */
-void qd_error_clear();
+qd_error_t qd_error_clear();
 
 /**
  * @return Thread local error message. Includes text for error code.
@@ -96,4 +98,14 @@ qd_error_t qd_error_py_impl(const char *
 #define QD_ERROR_RET() do { if (qd_error_code()) return qd_error_code(); } 
while(0)
 #define QD_ERROR_PY_RET() do { if (qd_error_py()) return qd_error_code(); } 
while(0)
 
+/**
+ * Check for an errno error.
+ *
+ * If errnum is non-0, set error code QD_ERROR_SYSTEM with a message including 
the errno text.
+ * Otherwise, call qd_error_clear() and return QD_ERROR_NONE.
+ */
+#define qd_error_errno(errnum, fmt, ...) qd_error_impl(errnum, __FILE__, 
__LINE__, fmt, ##__VA_ARGS__)
+
+qd_error_t qd_error_errno_impl(int errnum, const char *file, int line, const 
char *fmt, ...);
+
 #endif

Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py?rev=1644532&r1=1644531&r2=1644532&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py 
(original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/config.py Wed 
Dec 10 22:17:29 2014
@@ -36,7 +36,10 @@ class Config(object):
         self.config_types = [e for e in schema.entity_types.itervalues()
                              if schema.is_configuration(e)]
         if filename:
-            self.load(filename)
+            try:
+                self.load(filename)
+            except Exception, e:
+                raise Exception("Cannot load configuration file %s: %s" % 
(filename, e))
         else:
             self.entities = []
 

Modified: qpid/dispatch/trunk/router/src/main.c
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/router/src/main.c?rev=1644532&r1=1644531&r2=1644532&view=diff
==============================================================================
--- qpid/dispatch/trunk/router/src/main.c (original)
+++ qpid/dispatch/trunk/router/src/main.c Wed Dec 10 22:17:29 2014
@@ -25,7 +25,9 @@
 #include <pwd.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <string.h>
 #include <getopt.h>
+#include <errno.h>
 #include "config.h"
 
 static int            exit_with_sigint = 0;
@@ -82,16 +84,31 @@ static void server_signal_handler(void*
 static void check(int fd) {
     if (qd_error_code()) {
         qd_log(log_source, QD_LOG_CRITICAL, "Router start-up failed: %s", 
qd_error_message());
-        if (fd > 0)
-        write(fd, "X", 1);
+        write(fd, qd_error_message(), strlen(qd_error_message()));
+        char eos = '\0';
+        write(fd, &eos, 1);
+        close(fd);
         exit(1);
     }
 }
 
+#define fail(fd, fmt, ...)                                      \
+    do {                                                        \
+        if (!qd_error_errno(errno, fmt, ##__VA_ARGS__))         \
+            qd_error(QD_ERROR_RUNTIME, fmt, ##__VA_ARGS__);     \
+        check(fd);                                              \
+    } while(false)
 
 static void main_process(const char *config_path, const char *python_pkgdir, 
int fd)
 {
     qd_error_clear();
+    struct stat st;
+    if (stat(python_pkgdir, &st)) fail(fd, "Cannot stat python library path 
'%s'", python_pkgdir);
+    if (!S_ISDIR(st.st_mode)) {
+        qd_error(QD_ERROR_RUNTIME, "Python library path '%s' not a directory", 
python_pkgdir);
+        check(fd);
+    }
+
     dispatch = qd_dispatch(python_pkgdir);
     check(fd);
     log_source = qd_log_source("MAIN"); /* Logging is initialized by 
qd_dispatch. */
@@ -108,7 +125,7 @@ static void main_process(const char *con
     signal(SIGINT,  signal_handler);
 
     if (fd > 0) {
-        write(fd, "0", 1); // Success signal
+        dprintf(fd, "ok"); // Success signal
         close(fd);
     }
 
@@ -155,11 +172,7 @@ static void daemon_process(const char *c
         //
         // Detach any terminals and create an independent session
         //
-        if (setsid() < 0) {
-            write(pipefd[1], "1", 1);
-            exit(0);
-        }
-
+        if (setsid() < 0) fail(pipefd[1], "Cannot start a new session");
         //
         // Second fork
         //
@@ -174,45 +187,27 @@ static void daemon_process(const char *c
             close(1);
             close(0);
             int fd = open("/dev/null", O_RDWR);
-            if (fd != 0) {
-                write(pipefd[1], "2", 1);
-                exit(0);
-            }
-            if (dup(fd) < 0) {
-                write(pipefd[1], "3", 1);
-                exit(0);
-            }
-            if (dup(fd) < 0) {
-                write(pipefd[1], "4", 1);
-                exit(0);
-            }
+            if (fd != 0) fail(pipefd[1], "Can't redirect stdin to /dev/null");
+            if (dup(fd) < 0) fail(pipefd[1], "Can't redirect stdout to 
/dev/null");
+            if (dup(fd) < 0) fail(pipefd[1], "Can't redirect stderr 
/dev/null");
 
             //
             // Set the umask to 0
             //
-            if (umask(0) < 0) {
-                write(pipefd[1], "5", 1);
-                exit(0);
-            }
+            if (umask(0) < 0) fail(pipefd[1], "Can't set umask");
 
             //
             // Set the current directory to "/" to avoid blocking
             // mount points
             //
-            if (chdir("/") < 0) {
-                write(pipefd[1], "6", 1);
-                exit(0);
-            }
+            if (chdir("/") < 0) fail(pipefd[1], "Can't chdir /");
 
             //
             // If a pidfile was provided, write the daemon pid there.
             //
             if (pidfile) {
                 FILE *pf = fopen(pidfile, "w");
-                if (pf == 0) {
-                    write(pipefd[1], "7", 1);
-                    exit(0);
-                }
+                if (pf == 0) fail(pipefd[1], "Can't write pidfile %s", 
pidfile);
                 fprintf(pf, "%d\n", getpid());
                 fclose(pf);
             }
@@ -223,18 +218,9 @@ static void daemon_process(const char *c
             //
             if (user) {
                 struct passwd *pwd = getpwnam(user);
-                if (pwd == 0) {
-                    write(pipefd[1], "8", 1);
-                    exit(0);
-                }
-                if (setuid(pwd->pw_uid) < 0) {
-                    write(pipefd[1], "9", 1);
-                    exit(0);
-                }
-                if (setgid(pwd->pw_gid) < 0) {
-                    write(pipefd[1], "A", 1);
-                    exit(0);
-                }
+                if (pwd == 0) fail(pipefd[1], "Can't look up user %s", user);
+                if (setuid(pwd->pw_uid) < 0) fail(pipefd[1], "Can't set user 
ID for user %s", user);
+                if (setgid(pwd->pw_gid) < 0) fail(pipefd[1], "Cant set group 
ID for user %s", user);
             }
 
             main_process(config_path, python_pkgdir, pipefd[1]);
@@ -249,16 +235,17 @@ static void daemon_process(const char *c
         // Wait for a success signal ('0') from the daemon process.
         // If we get success, exit with 0.  Otherwise, exit with 1.
         //
-        char code;
         close(pipefd[1]); // Close write end.
-        if (read(pipefd[0], &code, 1) < 0) {
+        char result[256];
+        memset(result, 0, sizeof(result));
+        if (read(pipefd[0], &result, sizeof(result)-1) < 0) {
             perror("Error reading inter-process pipe");
             exit(1);
         }
 
-        if (code == '0')
+        if (strcmp(result, "ok") == 0)
             exit(0);
-        fprintf(stderr, "Error occurred during daemon initialization, please 
see logs.  [code=%c]\n", code);
+        fprintf(stderr, "Daemon error: %s\n", result);
         exit(1);
     }
 }
@@ -337,6 +324,7 @@ int main(int argc, char **argv)
         usage(argv);
         exit(1);
     }
+
     if (daemon_mode)
         daemon_process(config_path, python_pkgdir, pidfile, user);
     else

Modified: qpid/dispatch/trunk/src/error.c
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/error.c?rev=1644532&r1=1644531&r2=1644532&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/error.c (original)
+++ qpid/dispatch/trunk/src/error.c Wed Dec 10 22:17:29 2014
@@ -23,6 +23,7 @@
 #include <qpid/dispatch/log.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <errno.h>
 #include "log_private.h"
 #include "aprintf.h"
 
@@ -36,7 +37,8 @@ static const char *qd_error_names[] = {
  "Configuration",
  "Type",
  "Value",
- "Run Time"
+ "Run Time",
+ "System"
 };
 ENUM_DEFINE(qd_error, qd_error_names);
 
@@ -60,11 +62,13 @@ qd_error_t qd_error_impl(qd_error_t code
     if (code) {
         char *begin = ts.error_message;
         char *end = begin + ERROR_MAX;
-        const char* name = qd_error_name(code);
-        if (name)
-            aprintf(&begin, end, "%s: ", name);
-        else
-            aprintf(&begin, end, "%d: ", code);
+        /* FIXME aconway 2014-12-10:  */
+        (void)aprintf;
+        /* const char* name = qd_error_name(code); */
+        /* if (name) */
+        /*     aprintf(&begin, end, "%s: ", name); */
+        /* else */
+        /*     aprintf(&begin, end, "%d: ", code); */
         va_list arglist;
         va_start(arglist, fmt);
         vaprintf(&begin, end, fmt, arglist);
@@ -78,9 +82,10 @@ qd_error_t qd_error_impl(qd_error_t code
     return 0;
 }
 
-void qd_error_clear() {
+qd_error_t qd_error_clear() {
     ts.error_code = 0;
     snprintf(ts.error_message, ERROR_MAX, "No Error");
+    return QD_ERROR_NONE;
 }
 
 const char* qd_error_message() {
@@ -168,3 +173,23 @@ qd_error_t qd_error_py_impl(const char *
     }
     return qd_error_code();
 }
+
+qd_error_t qd_error_errno_impl(int errnum, const char *file, int line, const 
char *fmt, ...) {
+    if (errnum) {
+        ts.error_code = QD_ERROR_SYSTEM;
+        char buf[ERROR_MAX];
+        char *errstr = strerror_r(errno, buf, sizeof(buf));
+
+        char *begin = ts.error_message;
+        char *end = begin + ERROR_MAX;
+        va_list arglist;
+        va_start(arglist, fmt);
+        vaprintf(&begin, end, fmt, arglist);
+        va_end(arglist);
+        aprintf(&begin, end, ": %s", errstr);
+        qd_log_impl(log_source, QD_LOG_ERROR, file, line, "%s", 
qd_error_message());
+        return qd_error_code();
+    }
+    else
+        return qd_error_clear();
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to