Move futex.c/.h to libcommon
[lttng-tools.git] / src / bin / lttng-sessiond / main.c
index 9b2d1fe0079c91753877dec1ca724466187ac9f3..e1b3a828bc66f4ac68693ca55944cfbb8a9101c9 100644 (file)
@@ -2,22 +2,21 @@
  * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
  *                      Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; only version 2 of the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 only,
+ * as published by the Free Software Foundation.
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA  02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #define _GNU_SOURCE
-#include <fcntl.h>
 #include <getopt.h>
 #include <grp.h>
 #include <limits.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include <urcu/futex.h>
+#include <urcu/uatomic.h>
 #include <unistd.h>
 #include <config.h>
 
 #include <common/common.h>
 #include <common/compat/poll.h>
+#include <common/compat/socket.h>
 #include <common/defaults.h>
 #include <common/kernel-consumer/kernel-consumer.h>
 #include <common/ust-consumer/ust-consumer.h>
+#include <common/futex.h>
 
 #include "lttng-sessiond.h"
 #include "channel.h"
 #include "context.h"
 #include "event.h"
-#include "futex.h"
 #include "kernel.h"
 #include "modprobe.h"
 #include "shm.h"
 #include "ust-ctl.h"
 #include "utils.h"
+#include "fd-limit.h"
 
 #define CONSUMERD_FILE "lttng-consumerd"
 
@@ -81,14 +82,10 @@ const char default_tracing_group[] = DEFAULT_TRACING_GROUP;
 const char default_ust_sock_dir[] = DEFAULT_UST_SOCK_DIR;
 const char default_global_apps_pipe[] = DEFAULT_GLOBAL_APPS_PIPE;
 
-/* Variables */
-int opt_verbose;    /* Not static for lttngerr.h */
-int opt_verbose_consumer;    /* Not static for lttngerr.h */
-int opt_quiet;      /* Not static for lttngerr.h */
-
 const char *progname;
 const char *opt_tracing_group;
 static int opt_sig_parent;
+static int opt_verbose_consumer;
 static int opt_daemon;
 static int opt_no_kernel;
 static int is_root;                    /* Set to 1 if the daemon is running as root */
@@ -100,16 +97,22 @@ static struct consumer_data kconsumer_data = {
        .type = LTTNG_CONSUMER_KERNEL,
        .err_unix_sock_path = DEFAULT_KCONSUMERD_ERR_SOCK_PATH,
        .cmd_unix_sock_path = DEFAULT_KCONSUMERD_CMD_SOCK_PATH,
+       .err_sock = -1,
+       .cmd_sock = -1,
 };
 static struct consumer_data ustconsumer64_data = {
        .type = LTTNG_CONSUMER64_UST,
        .err_unix_sock_path = DEFAULT_USTCONSUMERD64_ERR_SOCK_PATH,
        .cmd_unix_sock_path = DEFAULT_USTCONSUMERD64_CMD_SOCK_PATH,
+       .err_sock = -1,
+       .cmd_sock = -1,
 };
 static struct consumer_data ustconsumer32_data = {
        .type = LTTNG_CONSUMER32_UST,
        .err_unix_sock_path = DEFAULT_USTCONSUMERD32_ERR_SOCK_PATH,
        .cmd_unix_sock_path = DEFAULT_USTCONSUMERD32_CMD_SOCK_PATH,
+       .err_sock = -1,
+       .cmd_sock = -1,
 };
 
 static int dispatch_thread_exit;
@@ -122,22 +125,22 @@ static char client_unix_sock_path[PATH_MAX];
 static char wait_shm_path[PATH_MAX];
 
 /* Sockets and FDs */
-static int client_sock;
-static int apps_sock;
-static int kernel_tracer_fd;
-static int kernel_poll_pipe[2];
+static int client_sock = -1;
+static int apps_sock = -1;
+static int kernel_tracer_fd = -1;
+static int kernel_poll_pipe[2] = { -1, -1 };
 
 /*
  * Quit pipe for all threads. This permits a single cancellation point
  * for all threads when receiving an event on the pipe.
  */
-static int thread_quit_pipe[2];
+static int thread_quit_pipe[2] = { -1, -1 };
 
 /*
  * This pipe is used to inform the thread managing application communication
  * that a command is queued and ready to be processed.
  */
-static int apps_cmd_pipe[2];
+static int apps_cmd_pipe[2] = { -1, -1 };
 
 /* Pthread, Mutexes and Semaphores */
 static pthread_t apps_thread;
@@ -176,6 +179,40 @@ static const char *consumerd64_bin = CONFIG_CONSUMERD64_BIN;
 static const char *consumerd32_libdir = CONFIG_CONSUMERD32_LIBDIR;
 static const char *consumerd64_libdir = CONFIG_CONSUMERD64_LIBDIR;
 
+/*
+ * Consumer daemon state which is changed when spawning it, killing it or in
+ * case of a fatal error.
+ */
+enum consumerd_state {
+       CONSUMER_STARTED = 1,
+       CONSUMER_STOPPED = 2,
+       CONSUMER_ERROR   = 3,
+};
+
+/*
+ * This consumer daemon state is used to validate if a client command will be
+ * able to reach the consumer. If not, the client is informed. For instance,
+ * doing a "lttng start" when the consumer state is set to ERROR will return an
+ * error to the client.
+ *
+ * The following example shows a possible race condition of this scheme:
+ *
+ * consumer thread error happens
+ *                                    client cmd arrives
+ *                                    client cmd checks state -> still OK
+ * consumer thread exit, sets error
+ *                                    client cmd try to talk to consumer
+ *                                    ...
+ *
+ * However, since the consumer is a different daemon, we have no way of making
+ * sure the command will reach it safely even with this state flag. This is why
+ * we consider that up to the state validation during command processing, the
+ * command is safe. After that, we can not guarantee the correctness of the
+ * client request vis-a-vis the consumer.
+ */
+static enum consumerd_state ust_consumerd_state;
+static enum consumerd_state kernel_consumerd_state;
+
 static
 void setup_consumerd_path(void)
 {
@@ -295,14 +332,22 @@ static gid_t allowed_group(void)
  */
 static int init_thread_quit_pipe(void)
 {
-       int ret;
+       int ret, i;
 
-       ret = pipe2(thread_quit_pipe, O_CLOEXEC);
+       ret = pipe(thread_quit_pipe);
        if (ret < 0) {
-               perror("thread quit pipe");
+               PERROR("thread quit pipe");
                goto error;
        }
 
+       for (i = 0; i < 2; i++) {
+               ret = fcntl(thread_quit_pipe[i], F_SETFD, FD_CLOEXEC);
+               if (ret < 0) {
+                       PERROR("fcntl");
+                       goto error;
+               }
+       }
+
 error:
        return ret;
 }
@@ -314,7 +359,7 @@ error:
 static void teardown_kernel_session(struct ltt_session *session)
 {
        if (!session->kernel_session) {
-               DBG3("No kernel session when tearingdown session");
+               DBG3("No kernel session when tearing down session");
                return;
        }
 
@@ -324,7 +369,8 @@ static void teardown_kernel_session(struct ltt_session *session)
         * If a custom kernel consumer was registered, close the socket before
         * tearing down the complete kernel session structure
         */
-       if (session->kernel_session->consumer_fd != kconsumer_data.cmd_sock) {
+       if (kconsumer_data.cmd_sock >= 0 &&
+                       session->kernel_session->consumer_fd != kconsumer_data.cmd_sock) {
                lttcomm_close_unix_sock(session->kernel_session->consumer_fd);
        }
 
@@ -340,7 +386,7 @@ static void teardown_ust_session(struct ltt_session *session)
        int ret;
 
        if (!session->ust_session) {
-               DBG3("No UST session when tearingdown session");
+               DBG3("No UST session when tearing down session");
                return;
        }
 
@@ -378,7 +424,7 @@ static void stop_threads(void)
  */
 static void cleanup(void)
 {
-       int ret;
+       int ret, i;
        char *cmd;
        struct ltt_session *sess, *stmp;
 
@@ -397,7 +443,7 @@ static void cleanup(void)
        }
        free(cmd);
 
-       DBG("Cleaning up all session");
+       DBG("Cleaning up all sessions");
 
        /* Destroy session list mutex */
        if (session_list_ptr != NULL) {
@@ -419,13 +465,43 @@ static void cleanup(void)
 
        if (is_root && !opt_no_kernel) {
                DBG2("Closing kernel fd");
-               close(kernel_tracer_fd);
+               if (kernel_tracer_fd >= 0) {
+                       ret = close(kernel_tracer_fd);
+                       if (ret) {
+                               PERROR("close");
+                       }
+               }
                DBG("Unloading kernel modules");
                modprobe_remove_lttng_all();
        }
 
-       close(thread_quit_pipe[0]);
-       close(thread_quit_pipe[1]);
+       /*
+        * Closing all pipes used for communication between threads.
+        */
+       for (i = 0; i < 2; i++) {
+               if (kernel_poll_pipe[i] >= 0) {
+                       ret = close(kernel_poll_pipe[i]);
+                       if (ret) {
+                               PERROR("close");
+                       }
+               }
+       }
+       for (i = 0; i < 2; i++) {
+               if (thread_quit_pipe[i] >= 0) {
+                       ret = close(thread_quit_pipe[i]);
+                       if (ret) {
+                               PERROR("close");
+                       }
+               }
+       }
+       for (i = 0; i < 2; i++) {
+               if (apps_cmd_pipe[i] >= 0) {
+                       ret = close(apps_cmd_pipe[i]);
+                       if (ret) {
+                               PERROR("close");
+                       }
+               }
+       }
 
        /* <fun> */
        DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm"
@@ -489,7 +565,7 @@ static int send_kconsumer_channel_streams(struct consumer_data *consumer_data,
        DBG("Sending channel %d to consumer", lkm.u.channel.channel_key);
        ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
        if (ret < 0) {
-               perror("send consumer channel");
+               PERROR("send consumer channel");
                goto error;
        }
 
@@ -511,12 +587,12 @@ static int send_kconsumer_channel_streams(struct consumer_data *consumer_data,
                DBG("Sending stream %d to consumer", lkm.u.stream.stream_key);
                ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
                if (ret < 0) {
-                       perror("send consumer stream");
+                       PERROR("send consumer stream");
                        goto error;
                }
                ret = lttcomm_send_fds_unix_sock(sock, &stream->fd, 1);
                if (ret < 0) {
-                       perror("send consumer stream ancillary data");
+                       PERROR("send consumer stream ancillary data");
                        goto error;
                }
        }
@@ -542,21 +618,21 @@ static int send_kconsumer_session_streams(struct consumer_data *consumer_data,
 
        DBG("Sending metadata stream fd");
 
-       /* Extra protection. It's NOT supposed to be set to 0 at this point */
-       if (session->consumer_fd == 0) {
+       /* Extra protection. It's NOT supposed to be set to -1 at this point */
+       if (session->consumer_fd < 0) {
                session->consumer_fd = consumer_data->cmd_sock;
        }
 
-       if (session->metadata_stream_fd != 0) {
+       if (session->metadata_stream_fd >= 0) {
                /* Send metadata channel fd */
                lkm.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
                lkm.u.channel.channel_key = session->metadata->fd;
                lkm.u.channel.max_sb_size = session->metadata->conf->attr.subbuf_size;
                lkm.u.channel.mmap_len = 0;     /* for kernel */
-               DBG("Sending metadata channel %d to consumer", lkm.u.stream.stream_key);
+               DBG("Sending metadata channel %d to consumer", lkm.u.channel.channel_key);
                ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
                if (ret < 0) {
-                       perror("send consumer channel");
+                       PERROR("send consumer channel");
                        goto error;
                }
 
@@ -574,12 +650,12 @@ static int send_kconsumer_session_streams(struct consumer_data *consumer_data,
                DBG("Sending metadata stream %d to consumer", lkm.u.stream.stream_key);
                ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
                if (ret < 0) {
-                       perror("send consumer stream");
+                       PERROR("send consumer stream");
                        goto error;
                }
                ret = lttcomm_send_fds_unix_sock(sock, &session->metadata_stream_fd, 1);
                if (ret < 0) {
-                       perror("send consumer stream");
+                       PERROR("send consumer stream");
                        goto error;
                }
        }
@@ -640,7 +716,7 @@ static int setup_lttng_msg(struct command_ctx *cmd_ctx, size_t size)
 
        cmd_ctx->llm = zmalloc(sizeof(struct lttcomm_lttng_msg) + buf_size);
        if (cmd_ctx->llm == NULL) {
-               perror("zmalloc");
+               PERROR("zmalloc");
                ret = -ENOMEM;
                goto error;
        }
@@ -721,8 +797,8 @@ static int update_kernel_stream(struct consumer_data *consumer_data, int fd)
                        continue;
                }
 
-               /* This is not suppose to be 0 but this is an extra security check */
-               if (session->kernel_session->consumer_fd == 0) {
+               /* This is not suppose to be -1 but this is an extra security check */
+               if (session->kernel_session->consumer_fd < 0) {
                        session->kernel_session->consumer_fd = consumer_data->cmd_sock;
                }
 
@@ -769,12 +845,18 @@ static void update_ust_app(int app_sock)
 {
        struct ltt_session *sess, *stmp;
 
+       session_lock_list();
+
        /* For all tracing session(s) */
        cds_list_for_each_entry_safe(sess, stmp, &session_list_ptr->head, list) {
+               session_lock(sess);
                if (sess->ust_session) {
                        ust_app_global_update(sess->ust_session, app_sock);
                }
+               session_unlock(sess);
        }
+
+       session_unlock_list();
 }
 
 /*
@@ -794,7 +876,7 @@ static void *thread_manage_kernel(void *data)
 
        ret = create_thread_poll_set(&events, 2);
        if (ret < 0) {
-               goto error;
+               goto error_poll_create;
        }
 
        ret = lttng_poll_add(&events, kernel_poll_pipe[0], LPOLLIN);
@@ -825,8 +907,15 @@ static void *thread_manage_kernel(void *data)
                lttng_poll_reset(&events);
 
                /* Poll infinite value of time */
+       restart:
                ret = lttng_poll_wait(&events, -1);
                if (ret < 0) {
+                       /*
+                        * Restart interrupted system call.
+                        */
+                       if (errno == EINTR) {
+                               goto restart;
+                       }
                        goto error;
                } else if (ret == 0) {
                        /* Should not happen since timeout is infinite */
@@ -872,12 +961,9 @@ static void *thread_manage_kernel(void *data)
        }
 
 error:
-       DBG("Kernel thread dying");
-       close(kernel_poll_pipe[0]);
-       close(kernel_poll_pipe[1]);
-
        lttng_poll_clean(&events);
-
+error_poll_create:
+       DBG("Kernel thread dying");
        return NULL;
 }
 
@@ -886,7 +972,7 @@ error:
  */
 static void *thread_manage_consumer(void *data)
 {
-       int sock = 0, i, ret, pollfd;
+       int sock = -1, i, ret, pollfd;
        uint32_t revents, nb_fd;
        enum lttcomm_return_code code;
        struct lttng_poll_event events;
@@ -896,7 +982,7 @@ static void *thread_manage_consumer(void *data)
 
        ret = lttcomm_listen_unix_sock(consumer_data->err_sock);
        if (ret < 0) {
-               goto error;
+               goto error_listen;
        }
 
        /*
@@ -905,7 +991,7 @@ static void *thread_manage_consumer(void *data)
         */
        ret = create_thread_poll_set(&events, 2);
        if (ret < 0) {
-               goto error;
+               goto error_poll;
        }
 
        ret = lttng_poll_add(&events, consumer_data->err_sock, LPOLLIN | LPOLLRDHUP);
@@ -916,8 +1002,15 @@ static void *thread_manage_consumer(void *data)
        nb_fd = LTTNG_POLL_GETNB(&events);
 
        /* Inifinite blocking call, waiting for transmission */
+restart:
        ret = lttng_poll_wait(&events, -1);
        if (ret < 0) {
+               /*
+                * Restart interrupted system call.
+                */
+               if (errno == EINTR) {
+                       goto restart;
+               }
                goto error;
        }
 
@@ -987,8 +1080,15 @@ static void *thread_manage_consumer(void *data)
        nb_fd = LTTNG_POLL_GETNB(&events);
 
        /* Inifinite blocking call, waiting for transmission */
+restart_poll:
        ret = lttng_poll_wait(&events, -1);
        if (ret < 0) {
+               /*
+                * Restart interrupted system call.
+                */
+               if (errno == EINTR) {
+                       goto restart_poll;
+               }
                goto error;
        }
 
@@ -1023,16 +1123,44 @@ static void *thread_manage_consumer(void *data)
        ERR("consumer return code : %s", lttcomm_get_readable_code(-code));
 
 error:
-       DBG("consumer thread dying");
-       close(consumer_data->err_sock);
-       close(consumer_data->cmd_sock);
-       close(sock);
+       /* Immediately set the consumerd state to stopped */
+       if (consumer_data->type == LTTNG_CONSUMER_KERNEL) {
+               uatomic_set(&kernel_consumerd_state, CONSUMER_ERROR);
+       } else if (consumer_data->type == LTTNG_CONSUMER64_UST ||
+                       consumer_data->type == LTTNG_CONSUMER32_UST) {
+               uatomic_set(&ust_consumerd_state, CONSUMER_ERROR);
+       } else {
+               /* Code flow error... */
+               assert(0);
+       }
+
+       if (consumer_data->err_sock >= 0) {
+               ret = close(consumer_data->err_sock);
+               if (ret) {
+                       PERROR("close");
+               }
+       }
+       if (consumer_data->cmd_sock >= 0) {
+               ret = close(consumer_data->cmd_sock);
+               if (ret) {
+                       PERROR("close");
+               }
+       }
+       if (sock >= 0) {
+               ret = close(sock);
+               if (ret) {
+                       PERROR("close");
+               }
+       }
 
        unlink(consumer_data->err_unix_sock_path);
        unlink(consumer_data->cmd_unix_sock_path);
        consumer_data->pid = 0;
 
        lttng_poll_clean(&events);
+error_poll:
+error_listen:
+       DBG("consumer thread cleanup completed");
 
        return NULL;
 }
@@ -1054,7 +1182,7 @@ static void *thread_manage_apps(void *data)
 
        ret = create_thread_poll_set(&events, 2);
        if (ret < 0) {
-               goto error;
+               goto error_poll_create;
        }
 
        ret = lttng_poll_add(&events, apps_cmd_pipe[0], LPOLLIN | LPOLLRDHUP);
@@ -1071,8 +1199,15 @@ static void *thread_manage_apps(void *data)
                DBG("Apps thread polling on %d fds", nb_fd);
 
                /* Inifinite blocking call, waiting for transmission */
+       restart:
                ret = lttng_poll_wait(&events, -1);
                if (ret < 0) {
+                       /*
+                        * Restart interrupted system call.
+                        */
+                       if (errno == EINTR) {
+                               goto restart;
+                       }
                        goto error;
                }
 
@@ -1096,7 +1231,7 @@ static void *thread_manage_apps(void *data)
                                        /* Empty pipe */
                                        ret = read(apps_cmd_pipe[0], &ust_cmd, sizeof(ust_cmd));
                                        if (ret < 0 || ret < sizeof(ust_cmd)) {
-                                               perror("read apps cmd pipe");
+                                               PERROR("read apps cmd pipe");
                                                goto error;
                                        }
 
@@ -1132,8 +1267,10 @@ static void *thread_manage_apps(void *data)
                                                /*
                                                 * We just need here to monitor the close of the UST
                                                 * socket and poll set monitor those by default.
+                                                * Listen on POLLIN (even if we never expect any
+                                                * data) to ensure that hangup wakes us.
                                                 */
-                                               ret = lttng_poll_add(&events, ust_cmd.sock, 0);
+                                               ret = lttng_poll_add(&events, ust_cmd.sock, LPOLLIN);
                                                if (ret < 0) {
                                                        goto error;
                                                }
@@ -1165,12 +1302,9 @@ static void *thread_manage_apps(void *data)
        }
 
 error:
-       DBG("Application communication apps dying");
-       close(apps_cmd_pipe[0]);
-       close(apps_cmd_pipe[1]);
-
        lttng_poll_clean(&events);
-
+error_poll_create:
+       DBG("Application communication apps thread cleanup complete");
        rcu_thread_offline();
        rcu_unregister_thread();
        return NULL;
@@ -1217,7 +1351,7 @@ static void *thread_dispatch_ust_registration(void *data)
                        ret = write(apps_cmd_pipe[1], ust_cmd,
                                        sizeof(struct ust_command));
                        if (ret < 0) {
-                               perror("write apps cmd pipe");
+                               PERROR("write apps cmd pipe");
                                if (errno == EBADF) {
                                        /*
                                         * We can't inform the application thread to process
@@ -1245,7 +1379,7 @@ error:
  */
 static void *thread_registration_apps(void *data)
 {
-       int sock = 0, i, ret, pollfd;
+       int sock = -1, i, ret, pollfd;
        uint32_t revents, nb_fd;
        struct lttng_poll_event events;
        /*
@@ -1258,7 +1392,7 @@ static void *thread_registration_apps(void *data)
 
        ret = lttcomm_listen_unix_sock(apps_sock);
        if (ret < 0) {
-               goto error;
+               goto error_listen;
        }
 
        /*
@@ -1267,13 +1401,13 @@ static void *thread_registration_apps(void *data)
         */
        ret = create_thread_poll_set(&events, 2);
        if (ret < 0) {
-               goto error;
+               goto error_create_poll;
        }
 
        /* Add the application registration socket */
        ret = lttng_poll_add(&events, apps_sock, LPOLLIN | LPOLLRDHUP);
        if (ret < 0) {
-               goto error;
+               goto error_poll_add;
        }
 
        /* Notify all applications to register */
@@ -1290,8 +1424,15 @@ static void *thread_registration_apps(void *data)
                nb_fd = LTTNG_POLL_GETNB(&events);
 
                /* Inifinite blocking call, waiting for transmission */
+       restart:
                ret = lttng_poll_wait(&events, -1);
                if (ret < 0) {
+                       /*
+                        * Restart interrupted system call.
+                        */
+                       if (errno == EINTR) {
+                               goto restart;
+                       }
                        goto error;
                }
 
@@ -1320,7 +1461,7 @@ static void *thread_registration_apps(void *data)
                                        /* Create UST registration command for enqueuing */
                                        ust_cmd = zmalloc(sizeof(struct ust_command));
                                        if (ust_cmd == NULL) {
-                                               perror("ust command zmalloc");
+                                               PERROR("ust command zmalloc");
                                                goto error;
                                        }
 
@@ -1328,20 +1469,37 @@ static void *thread_registration_apps(void *data)
                                         * Using message-based transmissions to ensure we don't
                                         * have to deal with partially received messages.
                                         */
+                                       ret = lttng_fd_get(LTTNG_FD_APPS, 1);
+                                       if (ret < 0) {
+                                               ERR("Exhausted file descriptors allowed for applications.");
+                                               free(ust_cmd);
+                                               ret = close(sock);
+                                               if (ret) {
+                                                       PERROR("close");
+                                               }
+                                               sock = -1;
+                                               continue;
+                                       }
                                        ret = lttcomm_recv_unix_sock(sock, &ust_cmd->reg_msg,
                                                        sizeof(struct ust_register_msg));
                                        if (ret < 0 || ret < sizeof(struct ust_register_msg)) {
                                                if (ret < 0) {
-                                                       perror("lttcomm_recv_unix_sock register apps");
+                                                       PERROR("lttcomm_recv_unix_sock register apps");
                                                } else {
                                                        ERR("Wrong size received on apps register");
                                                }
                                                free(ust_cmd);
-                                               close(sock);
+                                               ret = close(sock);
+                                               if (ret) {
+                                                       PERROR("close");
+                                               }
+                                               lttng_fd_put(LTTNG_FD_APPS, 1);
+                                               sock = -1;
                                                continue;
                                        }
 
                                        ust_cmd->sock = sock;
+                                       sock = -1;
 
                                        DBG("UST registration received with pid:%d ppid:%d uid:%d"
                                                        " gid:%d sock:%d name:%s (version %d.%d)",
@@ -1367,16 +1525,29 @@ static void *thread_registration_apps(void *data)
        }
 
 error:
-       DBG("UST Registration thread dying");
-
        /* Notify that the registration thread is gone */
        notify_ust_apps(0);
 
-       close(apps_sock);
-       close(sock);
+       if (apps_sock >= 0) {
+               ret = close(apps_sock);
+               if (ret) {
+                       PERROR("close");
+               }
+       }
+       if (sock >= 0) {
+               ret = close(sock);
+               if (ret) {
+                       PERROR("close");
+               }
+               lttng_fd_put(LTTNG_FD_APPS, 1);
+       }
        unlink(apps_unix_sock_path);
 
+error_poll_add:
        lttng_poll_clean(&events);
+error_listen:
+error_create_poll:
+       DBG("UST Registration thread cleanup complete");
 
        return NULL;
 }
@@ -1616,17 +1787,17 @@ static pid_t spawn_consumerd(struct consumer_data *consumer_data)
                        break;
                }
                default:
-                       perror("unknown consumer type");
+                       PERROR("unknown consumer type");
                        exit(EXIT_FAILURE);
                }
                if (errno != 0) {
-                       perror("kernel start consumer exec");
+                       PERROR("kernel start consumer exec");
                }
                exit(EXIT_FAILURE);
        } else if (pid > 0) {
                ret = pid;
        } else {
-               perror("start consumer fork");
+               PERROR("start consumer fork");
                ret = -errno;
        }
 error:
@@ -1717,20 +1888,30 @@ static int init_kernel_tracer(void)
 
 error_version:
        modprobe_remove_lttng_control();
-       close(kernel_tracer_fd);
-       kernel_tracer_fd = 0;
+       ret = close(kernel_tracer_fd);
+       if (ret) {
+               PERROR("close");
+       }
+       kernel_tracer_fd = -1;
        return LTTCOMM_KERN_VERSION;
 
 error_modules:
-       close(kernel_tracer_fd);
+       ret = close(kernel_tracer_fd);
+       if (ret) {
+               PERROR("close");
+       }
 
 error_open:
        modprobe_remove_lttng_control();
 
 error:
        WARN("No kernel tracer available");
-       kernel_tracer_fd = 0;
-       return LTTCOMM_KERN_NA;
+       kernel_tracer_fd = -1;
+       if (!is_root) {
+               return LTTCOMM_NEED_ROOT_SESSIOND;
+       } else {
+               return LTTCOMM_KERN_NA;
+       }
 }
 
 /*
@@ -1743,10 +1924,10 @@ static int init_kernel_tracing(struct ltt_kernel_session *session)
        if (session->consumer_fds_sent == 0) {
                /*
                 * Assign default kernel consumer socket if no consumer assigned to the
-                * kernel session. At this point, it's NOT suppose to be 0 but this is
+                * kernel session. At this point, it's NOT supposed to be -1 but this is
                 * an extra security check.
                 */
-               if (session->consumer_fd == 0) {
+               if (session->consumer_fd < 0) {
                        session->consumer_fd = kconsumer_data.cmd_sock;
                }
 
@@ -1834,7 +2015,7 @@ static int create_kernel_session(struct ltt_session *session)
        }
 
        /* Set kernel consumer socket fd */
-       if (kconsumer_data.cmd_sock) {
+       if (kconsumer_data.cmd_sock >= 0) {
                session->kernel_session->consumer_fd = kconsumer_data.cmd_sock;
        }
 
@@ -2031,8 +2212,17 @@ static int list_lttng_ust_global_events(char *channel_name,
                case LTTNG_UST_FUNCTION:
                        tmp[i].type = LTTNG_EVENT_FUNCTION;
                        break;
-               case LTTNG_UST_TRACEPOINT_LOGLEVEL:
-                       tmp[i].type = LTTNG_EVENT_TRACEPOINT_LOGLEVEL;
+               }
+               tmp[i].loglevel = uevent->attr.loglevel;
+               switch (uevent->attr.loglevel_type) {
+               case LTTNG_UST_LOGLEVEL_ALL:
+                       tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+                       break;
+               case LTTNG_UST_LOGLEVEL_RANGE:
+                       tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
+                       break;
+               case LTTNG_UST_LOGLEVEL_SINGLE:
+                       tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
                        break;
                }
                i++;
@@ -2419,12 +2609,6 @@ error:
 
 /*
  * Command LTTNG_ENABLE_EVENT processed by the client thread.
- *
- * TODO: currently, both events and loglevels are kept within the same
- * namespace for UST global registry/app registery, so if an event
- * happen to have the same name as the loglevel (very unlikely though),
- * and an attempt is made to enable/disable both in the same session,
- * the first to be created will be the only one allowed to exist.
  */
 static int cmd_enable_event(struct ltt_session *session, int domain,
                char *channel_name, struct lttng_event *event)
@@ -2720,7 +2904,8 @@ static int cmd_start_trace(struct ltt_session *session)
        usess = session->ust_session;
 
        if (session->enabled) {
-               ret = LTTCOMM_UST_START_FAIL;
+               /* Already started. */
+               ret = LTTCOMM_TRACE_ALREADY_STARTED;
                goto error;
        }
 
@@ -2740,7 +2925,7 @@ static int cmd_start_trace(struct ltt_session *session)
                }
 
                /* Open kernel metadata stream */
-               if (ksession->metadata_stream_fd == 0) {
+               if (ksession->metadata_stream_fd < 0) {
                        ret = kernel_open_metadata_stream(ksession);
                        if (ret < 0) {
                                ERR("Kernel create metadata stream failed");
@@ -2812,7 +2997,7 @@ static int cmd_stop_trace(struct ltt_session *session)
        usess = session->ust_session;
 
        if (!session->enabled) {
-               ret = LTTCOMM_UST_STOP_FAIL;
+               ret = LTTCOMM_TRACE_ALREADY_STOPPED;
                goto error;
        }
 
@@ -2863,11 +3048,12 @@ error:
 /*
  * Command LTTNG_CREATE_SESSION processed by the client thread.
  */
-static int cmd_create_session(char *name, char *path, struct ucred *creds)
+static int cmd_create_session(char *name, char *path, lttng_sock_cred *creds)
 {
        int ret;
 
-       ret = session_create(name, path, creds->uid, creds->gid);
+       ret = session_create(name, path, LTTNG_SOCK_GET_UID_CRED(creds),
+                       LTTNG_SOCK_GET_GID_CRED(creds));
        if (ret != LTTCOMM_OK) {
                goto error;
        }
@@ -2896,7 +3082,7 @@ static int cmd_destroy_session(struct ltt_session *session, char *name)
         */
        ret = notify_thread_pipe(kernel_poll_pipe[1]);
        if (ret < 0) {
-               perror("write kernel poll pipe");
+               PERROR("write kernel poll pipe");
        }
 
        ret = session_destroy(session);
@@ -3117,11 +3303,30 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
 {
        int ret = LTTCOMM_OK;
        int need_tracing_session = 1;
+       int need_domain;
 
        DBG("Processing client command %d", cmd_ctx->lsm->cmd_type);
 
-       if (opt_no_kernel && cmd_ctx->lsm->domain.type == LTTNG_DOMAIN_KERNEL) {
-               ret = LTTCOMM_KERN_NA;
+       switch (cmd_ctx->lsm->cmd_type) {
+       case LTTNG_CREATE_SESSION:
+       case LTTNG_DESTROY_SESSION:
+       case LTTNG_LIST_SESSIONS:
+       case LTTNG_LIST_DOMAINS:
+       case LTTNG_START_TRACE:
+       case LTTNG_STOP_TRACE:
+               need_domain = 0;
+               break;
+       default:
+               need_domain = 1;
+       }
+
+       if (opt_no_kernel && need_domain
+                       && cmd_ctx->lsm->domain.type == LTTNG_DOMAIN_KERNEL) {
+               if (!is_root) {
+                       ret = LTTCOMM_NEED_ROOT_SESSIOND;
+               } else {
+                       ret = LTTCOMM_KERN_NA;
+               }
                goto error;
        }
 
@@ -3148,17 +3353,21 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
 
        /* Commands that DO NOT need a session. */
        switch (cmd_ctx->lsm->cmd_type) {
-       case LTTNG_CALIBRATE:
        case LTTNG_CREATE_SESSION:
+       case LTTNG_CALIBRATE:
        case LTTNG_LIST_SESSIONS:
        case LTTNG_LIST_TRACEPOINTS:
                need_tracing_session = 0;
                break;
        default:
                DBG("Getting session %s by name", cmd_ctx->lsm->session.name);
+               /*
+                * We keep the session list lock across _all_ commands
+                * for now, because the per-session lock does not
+                * handle teardown properly.
+                */
                session_lock_list();
                cmd_ctx->session = session_find_by_name(cmd_ctx->lsm->session.name);
-               session_unlock_list();
                if (cmd_ctx->session == NULL) {
                        if (cmd_ctx->lsm->session.name != NULL) {
                                ret = LTTCOMM_SESS_NOT_FOUND;
@@ -3174,18 +3383,21 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                break;
        }
 
+       if (!need_domain) {
+               goto skip_domain;
+       }
        /*
         * Check domain type for specific "pre-action".
         */
        switch (cmd_ctx->lsm->domain.type) {
        case LTTNG_DOMAIN_KERNEL:
                if (!is_root) {
-                       ret = LTTCOMM_KERN_NA;
+                       ret = LTTCOMM_NEED_ROOT_SESSIOND;
                        goto error;
                }
 
                /* Kernel tracer check */
-               if (kernel_tracer_fd == 0) {
+               if (kernel_tracer_fd == -1) {
                        /* Basically, load kernel tracer modules */
                        ret = init_kernel_tracer();
                        if (ret != 0) {
@@ -3193,6 +3405,12 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                        }
                }
 
+               /* Consumer is in an ERROR state. Report back to client */
+               if (uatomic_read(&kernel_consumerd_state) == CONSUMER_ERROR) {
+                       ret = LTTCOMM_NO_KERNCONSUMERD;
+                       goto error;
+               }
+
                /* Need a session for kernel command */
                if (need_tracing_session) {
                        if (cmd_ctx->session->kernel_session == NULL) {
@@ -3213,13 +3431,21 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                                        ret = LTTCOMM_KERN_CONSUMER_FAIL;
                                        goto error;
                                }
+                               uatomic_set(&kernel_consumerd_state, CONSUMER_STARTED);
                        } else {
                                pthread_mutex_unlock(&kconsumer_data.pid_mutex);
                        }
                }
+
                break;
        case LTTNG_DOMAIN_UST:
        {
+               /* Consumer is in an ERROR state. Report back to client */
+               if (uatomic_read(&ust_consumerd_state) == CONSUMER_ERROR) {
+                       ret = LTTCOMM_NO_USTCONSUMERD;
+                       goto error;
+               }
+
                if (need_tracing_session) {
                        if (cmd_ctx->session->ust_session == NULL) {
                                ret = create_ust_session(cmd_ctx->session,
@@ -3243,6 +3469,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                                }
 
                                ust_consumerd64_fd = ustconsumer64_data.cmd_sock;
+                               uatomic_set(&ust_consumerd_state, CONSUMER_STARTED);
                        } else {
                                pthread_mutex_unlock(&ustconsumer64_data.pid_mutex);
                        }
@@ -3257,7 +3484,9 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                                        ust_consumerd32_fd = -EINVAL;
                                        goto error;
                                }
+
                                ust_consumerd32_fd = ustconsumer32_data.cmd_sock;
+                               uatomic_set(&ust_consumerd_state, CONSUMER_STARTED);
                        } else {
                                pthread_mutex_unlock(&ustconsumer32_data.pid_mutex);
                        }
@@ -3267,6 +3496,26 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
        default:
                break;
        }
+skip_domain:
+
+       /* Validate consumer daemon state when start/stop trace command */
+       if (cmd_ctx->lsm->cmd_type == LTTNG_START_TRACE ||
+                       cmd_ctx->lsm->cmd_type == LTTNG_STOP_TRACE) {
+               switch (cmd_ctx->lsm->domain.type) {
+               case LTTNG_DOMAIN_UST:
+                       if (uatomic_read(&ust_consumerd_state) != CONSUMER_STARTED) {
+                               ret = LTTCOMM_NO_USTCONSUMERD;
+                               goto error;
+                       }
+                       break;
+               case LTTNG_DOMAIN_KERNEL:
+                       if (uatomic_read(&kernel_consumerd_state) != CONSUMER_STARTED) {
+                               ret = LTTCOMM_NO_KERNCONSUMERD;
+                               goto error;
+                       }
+                       break;
+               }
+       }
 
        /*
         * Check that the UID or GID match that of the tracing session.
@@ -3274,7 +3523,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
         */
        if (need_tracing_session) {
                if (!session_access_ok(cmd_ctx->session,
-                               cmd_ctx->creds.uid, cmd_ctx->creds.gid)) {
+                               LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds),
+                               LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds))) {
                        ret = LTTCOMM_EPERM;
                        goto error;
                }
@@ -3301,7 +3551,6 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                ret = cmd_disable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type,
                                cmd_ctx->lsm->u.disable.channel_name,
                                cmd_ctx->lsm->u.disable.name);
-               ret = LTTCOMM_OK;
                break;
        }
        case LTTNG_DISABLE_ALL_EVENT:
@@ -3384,6 +3633,11 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
        {
                ret = cmd_destroy_session(cmd_ctx->session,
                                cmd_ctx->lsm->session.name);
+               /*
+                * Set session to NULL so we do not unlock it after
+                * free.
+                */
+               cmd_ctx->session = NULL;
                break;
        }
        case LTTNG_LIST_DOMAINS:
@@ -3468,12 +3722,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                unsigned int nr_sessions;
 
                session_lock_list();
-               nr_sessions = lttng_sessions_count(cmd_ctx->creds.uid, cmd_ctx->creds.gid);
-               if (nr_sessions == 0) {
-                       ret = LTTCOMM_NO_SESSION;
-                       session_unlock_list();
-                       goto error;
-               }
+               nr_sessions = lttng_sessions_count(
+                               LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds),
+                               LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds));
+
                ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_session) * nr_sessions);
                if (ret < 0) {
                        session_unlock_list();
@@ -3482,7 +3734,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
 
                /* Filled the session array */
                list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload),
-                       cmd_ctx->creds.uid, cmd_ctx->creds.gid);
+                       LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds),
+                       LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds));
 
                session_unlock_list();
 
@@ -3519,6 +3772,9 @@ setup_error:
        if (cmd_ctx->session) {
                session_unlock(cmd_ctx->session);
        }
+       if (need_tracing_session) {
+               session_unlock_list();
+       }
 init_setup_error:
        return ret;
 }
@@ -3529,7 +3785,7 @@ init_setup_error:
  */
 static void *thread_manage_clients(void *data)
 {
-       int sock = 0, ret, i, pollfd;
+       int sock = -1, ret, i, pollfd;
        uint32_t revents, nb_fd;
        struct command_ctx *cmd_ctx = NULL;
        struct lttng_poll_event events;
@@ -3571,8 +3827,15 @@ static void *thread_manage_clients(void *data)
                nb_fd = LTTNG_POLL_GETNB(&events);
 
                /* Inifinite blocking call, waiting for transmission */
+       restart:
                ret = lttng_poll_wait(&events, -1);
                if (ret < 0) {
+                       /*
+                        * Restart interrupted system call.
+                        */
+                       if (errno == EINTR) {
+                               goto restart;
+                       }
                        goto error;
                }
 
@@ -3612,14 +3875,14 @@ static void *thread_manage_clients(void *data)
                /* Allocate context command to process the client request */
                cmd_ctx = zmalloc(sizeof(struct command_ctx));
                if (cmd_ctx == NULL) {
-                       perror("zmalloc cmd_ctx");
+                       PERROR("zmalloc cmd_ctx");
                        goto error;
                }
 
                /* Allocate data buffer for reception */
                cmd_ctx->lsm = zmalloc(sizeof(struct lttcomm_session_msg));
                if (cmd_ctx->lsm == NULL) {
-                       perror("zmalloc cmd_ctx->lsm");
+                       PERROR("zmalloc cmd_ctx->lsm");
                        goto error;
                }
 
@@ -3636,8 +3899,12 @@ static void *thread_manage_clients(void *data)
                                sizeof(struct lttcomm_session_msg), &cmd_ctx->creds);
                if (ret <= 0) {
                        DBG("Nothing recv() from client... continuing");
-                       close(sock);
-                       free(cmd_ctx);
+                       ret = close(sock);
+                       if (ret) {
+                               PERROR("close");
+                       }
+                       sock = -1;
+                       clean_command_ctx(&cmd_ctx);
                        continue;
                }
 
@@ -3672,7 +3939,11 @@ static void *thread_manage_clients(void *data)
                }
 
                /* End of transmission */
-               close(sock);
+               ret = close(sock);
+               if (ret) {
+                       PERROR("close");
+               }
+               sock = -1;
 
                clean_command_ctx(&cmd_ctx);
        }
@@ -3680,8 +3951,18 @@ static void *thread_manage_clients(void *data)
 error:
        DBG("Client thread dying");
        unlink(client_unix_sock_path);
-       close(client_sock);
-       close(sock);
+       if (client_sock >= 0) {
+               ret = close(client_sock);
+               if (ret) {
+                       PERROR("close");
+               }
+       }
+       if (sock >= 0) {
+               ret = close(sock);
+               if (ret) {
+                       PERROR("close");
+               }
+       }
 
        lttng_poll_clean(&events);
        clean_command_ctx(&cmd_ctx);
@@ -3810,11 +4091,11 @@ static int parse_args(int argc, char **argv)
                        opt_no_kernel = 1;
                        break;
                case 'q':
-                       opt_quiet = 1;
+                       lttng_opt_quiet = 1;
                        break;
                case 'v':
                        /* Verbose level can increase using multiple -v */
-                       opt_verbose += 1;
+                       lttng_opt_verbose += 1;
                        break;
                case 'Z':
                        opt_verbose_consumer += 1;
@@ -3865,7 +4146,7 @@ static int init_daemon_socket(void)
        ret = chmod(client_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
        if (ret < 0) {
                ERR("Set file permissions failed: %s", client_unix_sock_path);
-               perror("chmod");
+               PERROR("chmod");
                goto end;
        }
 
@@ -3882,7 +4163,7 @@ static int init_daemon_socket(void)
                        S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
        if (ret < 0) {
                ERR("Set file permissions failed: %s", apps_unix_sock_path);
-               perror("chmod");
+               PERROR("chmod");
                goto end;
        }
 
@@ -3897,24 +4178,19 @@ end:
  */
 static int check_existing_daemon(void)
 {
-       if (access(client_unix_sock_path, F_OK) < 0 &&
-                       access(apps_unix_sock_path, F_OK) < 0) {
-               return 0;
-       }
-
        /* Is there anybody out there ? */
        if (lttng_session_daemon_alive()) {
                return -EEXIST;
-       } else {
-               return 0;
        }
+
+       return 0;
 }
 
 /*
  * Set the tracing group gid onto the client socket.
  *
  * Race window between mkdir and chown is OK because we are going from more
- * permissive (root.root) to les permissive (root.tracing).
+ * permissive (root.root) to less permissive (root.tracing).
  */
 static int set_permissions(char *rundir)
 {
@@ -3932,35 +4208,42 @@ static int set_permissions(char *rundir)
        ret = chown(rundir, 0, gid);
        if (ret < 0) {
                ERR("Unable to set group on %s", rundir);
-               perror("chown");
+               PERROR("chown");
+       }
+
+       /* Ensure tracing group can search the run dir */
+       ret = chmod(rundir, S_IRWXU | S_IXGRP | S_IXOTH);
+       if (ret < 0) {
+               ERR("Unable to set permissions on %s", rundir);
+               PERROR("chmod");
        }
 
        /* lttng client socket path */
        ret = chown(client_unix_sock_path, 0, gid);
        if (ret < 0) {
                ERR("Unable to set group on %s", client_unix_sock_path);
-               perror("chown");
+               PERROR("chown");
        }
 
        /* kconsumer error socket path */
        ret = chown(kconsumer_data.err_unix_sock_path, 0, gid);
        if (ret < 0) {
                ERR("Unable to set group on %s", kconsumer_data.err_unix_sock_path);
-               perror("chown");
+               PERROR("chown");
        }
 
        /* 64-bit ustconsumer error socket path */
        ret = chown(ustconsumer64_data.err_unix_sock_path, 0, gid);
        if (ret < 0) {
                ERR("Unable to set group on %s", ustconsumer64_data.err_unix_sock_path);
-               perror("chown");
+               PERROR("chown");
        }
 
        /* 32-bit ustconsumer compat32 error socket path */
        ret = chown(ustconsumer32_data.err_unix_sock_path, 0, gid);
        if (ret < 0) {
                ERR("Unable to set group on %s", ustconsumer32_data.err_unix_sock_path);
-               perror("chown");
+               PERROR("chown");
        }
 
        DBG("All permissions are set");
@@ -3971,18 +4254,54 @@ end:
 
 /*
  * Create the pipe used to wake up the kernel thread.
+ * Closed in cleanup().
  */
 static int create_kernel_poll_pipe(void)
 {
-       return pipe2(kernel_poll_pipe, O_CLOEXEC);
+       int ret, i;
+
+       ret = pipe(kernel_poll_pipe);
+       if (ret < 0) {
+               PERROR("kernel poll pipe");
+               goto error;
+       }
+
+       for (i = 0; i < 2; i++) {
+               ret = fcntl(kernel_poll_pipe[i], F_SETFD, FD_CLOEXEC);
+               if (ret < 0) {
+                       PERROR("fcntl kernel_poll_pipe");
+                       goto error;
+               }
+       }
+
+error:
+       return ret;
 }
 
 /*
  * Create the application command pipe to wake thread_manage_apps.
+ * Closed in cleanup().
  */
 static int create_apps_cmd_pipe(void)
 {
-       return pipe2(apps_cmd_pipe, O_CLOEXEC);
+       int ret, i;
+
+       ret = pipe(apps_cmd_pipe);
+       if (ret < 0) {
+               PERROR("apps cmd pipe");
+               goto error;
+       }
+
+       for (i = 0; i < 2; i++) {
+               ret = fcntl(apps_cmd_pipe[i], F_SETFD, FD_CLOEXEC);
+               if (ret < 0) {
+                       PERROR("fcntl apps_cmd_pipe");
+                       goto error;
+               }
+       }
+
+error:
+       return ret;
 }
 
 /*
@@ -3994,7 +4313,7 @@ static int create_lttng_rundir(const char *rundir)
 
        DBG3("Creating LTTng run directory: %s", rundir);
 
-       ret = mkdir(rundir, S_IRWXU | S_IRWXG );
+       ret = mkdir(rundir, S_IRWXU);
        if (ret < 0) {
                if (errno != EEXIST) {
                        ERR("Unable to create %s", rundir);
@@ -4036,13 +4355,14 @@ static int set_consumer_sockets(struct consumer_data *consumer_data,
 
        DBG2("Creating consumer directory: %s", path);
 
-       ret = mkdir(path, S_IRWXU | S_IRWXG);
+       ret = mkdir(path, S_IRWXU);
        if (ret < 0) {
                if (errno != EEXIST) {
+                       PERROR("mkdir");
                        ERR("Failed to create %s", path);
                        goto error;
                }
-               ret = 0;
+               ret = -1;
        }
 
        /* Create the kconsumerd error unix socket */
@@ -4103,7 +4423,7 @@ static int set_signal_handler(void)
        sigset_t sigset;
 
        if ((ret = sigemptyset(&sigset)) < 0) {
-               perror("sigemptyset");
+               PERROR("sigemptyset");
                return ret;
        }
 
@@ -4111,17 +4431,17 @@ static int set_signal_handler(void)
        sa.sa_mask = sigset;
        sa.sa_flags = 0;
        if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) {
-               perror("sigaction");
+               PERROR("sigaction");
                return ret;
        }
 
        if ((ret = sigaction(SIGINT, &sa, NULL)) < 0) {
-               perror("sigaction");
+               PERROR("sigaction");
                return ret;
        }
 
        if ((ret = sigaction(SIGPIPE, &sa, NULL)) < 0) {
-               perror("sigaction");
+               PERROR("sigaction");
                return ret;
        }
 
@@ -4145,7 +4465,7 @@ static void set_ulimit(void)
 
        ret = setrlimit(RLIMIT_NOFILE, &lim);
        if (ret < 0) {
-               perror("failed to set open files limit");
+               PERROR("failed to set open files limit");
        }
 }
 
@@ -4179,7 +4499,7 @@ int main(int argc, char **argv)
        if (opt_daemon) {
                ret = daemon(0, 0);
                if (ret < 0) {
-                       perror("daemon");
+                       PERROR("daemon");
                        goto error;
                }
        }
@@ -4264,6 +4584,10 @@ int main(int argc, char **argv)
                }
        }
 
+       /* Set consumer initial state */
+       kernel_consumerd_state = CONSUMER_STOPPED;
+       ust_consumerd_state = CONSUMER_STOPPED;
+
        DBG("Client socket path %s", client_unix_sock_path);
        DBG("Application socket path %s", apps_unix_sock_path);
        DBG("LTTng run directory path: %s", rundir);
@@ -4302,6 +4626,12 @@ int main(int argc, char **argv)
                goto error;
        }
 
+       /*
+        * Init UST app hash table. Alloc hash table before this point since
+        * cleanup() can get called after that point.
+        */
+       ust_app_ht_alloc();
+
        /* After this point, we can safely call cleanup() with "goto exit" */
 
        /*
@@ -4324,6 +4654,8 @@ int main(int argc, char **argv)
                /* Set ulimit for open files */
                set_ulimit();
        }
+       /* init lttng_fd tracking must be done after set_ulimit. */
+       lttng_fd_init();
 
        ret = set_consumer_sockets(&ustconsumer64_data, rundir);
        if (ret < 0) {
@@ -4367,9 +4699,6 @@ int main(int argc, char **argv)
        /* Init UST command queue. */
        cds_wfq_init(&ust_cmd_queue.queue);
 
-       /* Init UST app hash table */
-       ust_app_ht_alloc();
-
        /*
         * Get session list pointer. This pointer MUST NOT be free(). This list is
         * statically declared in session.c
@@ -4383,7 +4712,7 @@ int main(int argc, char **argv)
        ret = pthread_create(&client_thread, NULL,
                        thread_manage_clients, (void *) NULL);
        if (ret != 0) {
-               perror("pthread_create clients");
+               PERROR("pthread_create clients");
                goto exit_client;
        }
 
@@ -4391,7 +4720,7 @@ int main(int argc, char **argv)
        ret = pthread_create(&dispatch_thread, NULL,
                        thread_dispatch_ust_registration, (void *) NULL);
        if (ret != 0) {
-               perror("pthread_create dispatch");
+               PERROR("pthread_create dispatch");
                goto exit_dispatch;
        }
 
@@ -4399,7 +4728,7 @@ int main(int argc, char **argv)
        ret = pthread_create(&reg_apps_thread, NULL,
                        thread_registration_apps, (void *) NULL);
        if (ret != 0) {
-               perror("pthread_create registration");
+               PERROR("pthread_create registration");
                goto exit_reg_apps;
        }
 
@@ -4407,7 +4736,7 @@ int main(int argc, char **argv)
        ret = pthread_create(&apps_thread, NULL,
                        thread_manage_apps, (void *) NULL);
        if (ret != 0) {
-               perror("pthread_create apps");
+               PERROR("pthread_create apps");
                goto exit_apps;
        }
 
@@ -4415,47 +4744,47 @@ int main(int argc, char **argv)
        ret = pthread_create(&kernel_thread, NULL,
                        thread_manage_kernel, (void *) NULL);
        if (ret != 0) {
-               perror("pthread_create kernel");
+               PERROR("pthread_create kernel");
                goto exit_kernel;
        }
 
        ret = pthread_join(kernel_thread, &status);
        if (ret != 0) {
-               perror("pthread_join");
+               PERROR("pthread_join");
                goto error;     /* join error, exit without cleanup */
        }
 
 exit_kernel:
        ret = pthread_join(apps_thread, &status);
        if (ret != 0) {
-               perror("pthread_join");
+               PERROR("pthread_join");
                goto error;     /* join error, exit without cleanup */
        }
 
 exit_apps:
        ret = pthread_join(reg_apps_thread, &status);
        if (ret != 0) {
-               perror("pthread_join");
+               PERROR("pthread_join");
                goto error;     /* join error, exit without cleanup */
        }
 
 exit_reg_apps:
        ret = pthread_join(dispatch_thread, &status);
        if (ret != 0) {
-               perror("pthread_join");
+               PERROR("pthread_join");
                goto error;     /* join error, exit without cleanup */
        }
 
 exit_dispatch:
        ret = pthread_join(client_thread, &status);
        if (ret != 0) {
-               perror("pthread_join");
+               PERROR("pthread_join");
                goto error;     /* join error, exit without cleanup */
        }
 
        ret = join_consumer_thread(&kconsumer_data);
        if (ret != 0) {
-               perror("join_consumer");
+               PERROR("join_consumer");
                goto error;     /* join error, exit without cleanup */
        }
 
This page took 0.045213 seconds and 4 git commands to generate.