* 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
#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>
#include <assert.h>
#include <config.h>
#include <urcu/compiler.h>
+#include <ulimit.h>
#include <common/defaults.h>
#include <common/common.h>
}
}
+/*
+ * 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
*/
/* 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);
* 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;
}
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;
}
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");
PERROR("close");
}
}
+error_poll_fcntl:
error_quit_pipe:
for (i = 0; i < 2; i++) {
int err;
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();
* 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;
}
*/
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;
}
#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.
partition_len = len >> cds_lfht_get_count_order_ulong(nr_threads);
work = calloc(nr_threads, sizeof(*work));
assert(work);
+ pthread_mutex_lock(<tng_libc_state_lock);
for (thread = 0; thread < nr_threads; thread++) {
work[thread].ht = ht;
work[thread].i = i;
ret = pthread_join(work[thread].thread_id, NULL);
assert(!ret);
}
+ pthread_mutex_unlock(<tng_libc_state_lock);
free(work);
}
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;
}
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(<tng_libc_state_lock);
+ ret = run_as_clone(cmd, data, uid, gid);
+ pthread_mutex_unlock(<tng_libc_state_lock);
+ return ret;
} else {
DBG("Using run_as_noclone");
return run_as_noclone(cmd, data, uid, gid);
*/
#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 */
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;
}