Merge branch 'master' into benchmark
authorDavid Goulet <dgoulet@efficios.com>
Thu, 12 Apr 2012 14:42:54 +0000 (10:42 -0400)
committerDavid Goulet <dgoulet@efficios.com>
Thu, 12 Apr 2012 14:42:54 +0000 (10:42 -0400)
README
src/bin/lttng-consumerd/lttng-consumerd.c
src/common/consumer.c
src/common/hashtable/rculfhash.c
src/common/kernel-consumer/kernel-consumer.c
src/common/runas.c
src/common/runas.h
src/common/ust-consumer/ust-consumer.c

diff --git a/README b/README
index 6c5da7959743fb708a14bde40e9fdf690957cad8..aabdf5a6267db9fd9b8032bc1cbf62f5ee473cd8 100644 (file)
--- a/README
+++ b/README
@@ -28,6 +28,8 @@ REQUIREMENTS:
 
       * Debian/Ubuntu package: libpopt-dev
 
+    - For kernel tracing: modprobe
+
 For developers using the git tree:
 
 This source tree is based on the autotools suite from GNU to simplify
index 32571bddf36cfc94483eaf0f180694ac21a99fae..9f2f02feba03897b7462de3250c863ec2ec37b55 100644 (file)
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/ipc.h>
+#include <sys/resource.h>
 #include <sys/shm.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
@@ -38,6 +39,7 @@
 #include <assert.h>
 #include <config.h>
 #include <urcu/compiler.h>
+#include <ulimit.h>
 
 #include <common/defaults.h>
 #include <common/common.h>
@@ -227,6 +229,25 @@ static void parse_args(int argc, char **argv)
        }
 }
 
+/*
+ * Set open files limit to unlimited. This daemon can open a large number of
+ * file descriptors in order to consumer multiple kernel traces.
+ */
+static void set_ulimit(void)
+{
+       int ret;
+       struct rlimit lim;
+
+       /* The kernel does not allowed an infinite limit for open files */
+       lim.rlim_cur = 65535;
+       lim.rlim_max = 65535;
+
+       ret = setrlimit(RLIMIT_NOFILE, &lim);
+       if (ret < 0) {
+               PERROR("failed to set open files limit");
+       }
+}
+
 /*
  * main
  */
@@ -272,6 +293,11 @@ int main(int argc, char **argv)
        /* Init */
        lttng_consumer_init();
 
+       if (!getuid()) {
+               /* Set limit for open files */
+               set_ulimit();
+       }
+
        /* create the consumer instance with and assign the callbacks */
        ctx = lttng_consumer_create(opt_type, lttng_consumer_read_subbuffer,
                NULL, lttng_consumer_on_recv_stream, NULL);
index f81de8d556a66149c75e59193c50a7d2c96741bd..ee5575262ec5667d448007a8ab82eec0607e19c9 100644 (file)
@@ -538,7 +538,7 @@ int consumer_update_poll_array(
         * increment i so nb_fd is the number of real FD.
         */
        (*pollfd)[i].fd = ctx->consumer_poll_pipe[0];
-       (*pollfd)[i].events = POLLIN;
+       (*pollfd)[i].events = POLLIN | POLLPRI;
        return i;
 }
 
@@ -562,7 +562,7 @@ restart:
                perror("Poll error");
                goto exit;
        }
-       if (consumer_sockpoll[0].revents == POLLIN) {
+       if (consumer_sockpoll[0].revents & (POLLIN | POLLPRI)) {
                DBG("consumer_should_quit wake up");
                goto exit;
        }
@@ -736,6 +736,20 @@ struct lttng_consumer_local_data *lttng_consumer_create(
                goto error_poll_pipe;
        }
 
+       /* set read end of the pipe to non-blocking */
+       ret = fcntl(ctx->consumer_poll_pipe[0], F_SETFL, O_NONBLOCK);
+       if (ret < 0) {
+               perror("fcntl O_NONBLOCK");
+               goto error_poll_fcntl;
+       }
+
+       /* set write end of the pipe to non-blocking */
+       ret = fcntl(ctx->consumer_poll_pipe[1], F_SETFL, O_NONBLOCK);
+       if (ret < 0) {
+               perror("fcntl O_NONBLOCK");
+               goto error_poll_fcntl;
+       }
+
        ret = pipe(ctx->consumer_should_quit);
        if (ret < 0) {
                perror("Error creating recv pipe");
@@ -760,6 +774,7 @@ error_thread_pipe:
                        PERROR("close");
                }
        }
+error_poll_fcntl:
 error_quit_pipe:
        for (i = 0; i < 2; i++) {
                int err;
@@ -933,8 +948,6 @@ void *lttng_consumer_thread_poll_fds(void *data)
        struct lttng_consumer_stream **local_stream = NULL;
        /* local view of consumer_data.fds_count */
        int nb_fd = 0;
-       char tmp;
-       int tmp2;
        struct lttng_consumer_local_data *ctx = data;
 
        rcu_register_thread();
@@ -1018,12 +1031,15 @@ void *lttng_consumer_thread_poll_fds(void *data)
                 * array. We want to prioritize array update over
                 * low-priority reads.
                 */
-               if (pollfd[nb_fd].revents & POLLIN) {
+               if (pollfd[nb_fd].revents & (POLLIN | POLLPRI)) {
+                       size_t pipe_readlen;
+                       char tmp;
+
                        DBG("consumer_poll_pipe wake up");
-                       tmp2 = read(ctx->consumer_poll_pipe[0], &tmp, 1);
-                       if (tmp2 < 0) {
-                               perror("read consumer poll");
-                       }
+                       /* Consume 1 byte of pipe data */
+                       do {
+                               pipe_readlen = read(ctx->consumer_poll_pipe[0], &tmp, 1);
+                       } while (pipe_readlen == -1 && errno == EINTR);
                        continue;
                }
 
@@ -1228,11 +1244,20 @@ end:
         */
        consumer_poll_timeout = LTTNG_CONSUMER_POLL_TIMEOUT;
 
-       /* wake up the polling thread */
-       ret = write(ctx->consumer_poll_pipe[1], "4", 1);
-       if (ret < 0) {
-               perror("poll pipe write");
-       }
+       /*
+        * Wake-up the other end by writing a null byte in the pipe
+        * (non-blocking). Important note: Because writing into the
+        * pipe is non-blocking (and therefore we allow dropping wakeup
+        * data, as long as there is wakeup data present in the pipe
+        * buffer to wake up the other end), the other end should
+        * perform the following sequence for waiting:
+        * 1) empty the pipe (reads).
+        * 2) perform update operation.
+        * 3) wait on the pipe (poll).
+        */
+       do {
+               ret = write(ctx->consumer_poll_pipe[1], "", 1);
+       } while (ret == -1UL && errno == EINTR);
        rcu_unregister_thread();
        return NULL;
 }
index 840de351bcf83f616116e4d4b937201505eecd4b..776f9f391fd0e74b2b6fbcaee4fe8bc14fe5d73d 100644 (file)
 #include "rculfhash-internal.h"
 #include "urcu-flavor.h"
 
+/*
+ * We need to lock pthread exit, which deadlocks __nptl_setxid in the
+ * runas clone.
+ * This work-around will be allowed to be removed when runas.c gets
+ * changed to do an exec() before issuing seteuid/setegid.
+ * See http://sourceware.org/bugzilla/show_bug.cgi?id=10184 for details.
+ */
+pthread_mutex_t lttng_libc_state_lock = PTHREAD_MUTEX_INITIALIZER;
+
 /*
  * Split-counters lazily update the global counter each 1024
  * addition/removal. It automatically keeps track of resize required.
@@ -1028,6 +1037,7 @@ void partition_resize_helper(struct cds_lfht *ht, unsigned long i,
        partition_len = len >> cds_lfht_get_count_order_ulong(nr_threads);
        work = calloc(nr_threads, sizeof(*work));
        assert(work);
+       pthread_mutex_lock(&lttng_libc_state_lock);
        for (thread = 0; thread < nr_threads; thread++) {
                work[thread].ht = ht;
                work[thread].i = i;
@@ -1042,6 +1052,7 @@ void partition_resize_helper(struct cds_lfht *ht, unsigned long i,
                ret = pthread_join(work[thread].thread_id, NULL);
                assert(!ret);
        }
+       pthread_mutex_unlock(&lttng_libc_state_lock);
        free(work);
 }
 
index 9abee1de8ad5d3bb01efdf2b04ada6270811de18..bbc31f8e3be14bdb3927c87a1aabb40e28e777b5 100644 (file)
@@ -295,11 +295,20 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                break;
        }
 end:
-       /* signal the poll thread */
-       ret = write(ctx->consumer_poll_pipe[1], "4", 1);
-       if (ret < 0) {
-               perror("write consumer poll");
-       }
+       /*
+        * Wake-up the other end by writing a null byte in the pipe
+        * (non-blocking). Important note: Because writing into the
+        * pipe is non-blocking (and therefore we allow dropping wakeup
+        * data, as long as there is wakeup data present in the pipe
+        * buffer to wake up the other end), the other end should
+        * perform the following sequence for waiting:
+        * 1) empty the pipe (reads).
+        * 2) perform update operation.
+        * 3) wait on the pipe (poll).
+        */
+       do {
+               ret = write(ctx->consumer_poll_pipe[1], "", 1);
+       } while (ret == -1UL && errno == EINTR);
 end_nosignal:
        return 0;
 }
index 7de566ddb9fce211bb0db34d3c95c24a7cf6b3af..2c2015aa2d5b8206bca9052320553f8da78d431d 100644 (file)
@@ -317,8 +317,13 @@ static
 int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
 {
        if (!getenv("LTTNG_DEBUG_NOCLONE")) {
+               int ret;
+
                DBG("Using run_as_clone");
-               return run_as_clone(cmd, data, uid, gid);
+               pthread_mutex_lock(&lttng_libc_state_lock);
+               ret = run_as_clone(cmd, data, uid, gid);
+               pthread_mutex_unlock(&lttng_libc_state_lock);
+               return ret;
        } else {
                DBG("Using run_as_noclone");
                return run_as_noclone(cmd, data, uid, gid);
index 356bb22863fe2c448fed98e8b7b90677868ba6fb..9840eb056942ad7eb56fb83ee8a3aef4c29d49e4 100644 (file)
  */
 
 #include <unistd.h>
+#include <pthread.h>
 
 int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid);
 int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid);
 int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid);
 
+/*
+ * We need to lock pthread exit, which deadlocks __nptl_setxid in the
+ * clone.
+ */
+extern pthread_mutex_t lttng_libc_state_lock;
+
 #endif /* _RUNAS_H */
index bfdb7e968fe9aa77ba9ad922e8fb6bf8748f4353..2b55fd4637ead2b056fcafecc47ef5504d7c5df5 100644 (file)
@@ -257,11 +257,20 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                break;
        }
 end:
-       /* signal the poll thread */
-       ret = write(ctx->consumer_poll_pipe[1], "4", 1);
-       if (ret < 0) {
-               PERROR("write consumer poll");
-       }
+       /*
+        * Wake-up the other end by writing a null byte in the pipe
+        * (non-blocking). Important note: Because writing into the
+        * pipe is non-blocking (and therefore we allow dropping wakeup
+        * data, as long as there is wakeup data present in the pipe
+        * buffer to wake up the other end), the other end should
+        * perform the following sequence for waiting:
+        * 1) empty the pipe (reads).
+        * 2) perform update operation.
+        * 3) wait on the pipe (poll).
+        */
+       do {
+               ret = write(ctx->consumer_poll_pipe[1], "", 1);
+       } while (ret == -1UL && errno == EINTR);
 end_nosignal:
        return 0;
 }
This page took 0.033751 seconds and 4 git commands to generate.