* 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 <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 "shm.h"
#include "ust-ctl.h"
#include "utils.h"
+#include "fd-limit.h"
#define CONSUMERD_FILE "lttng-consumerd"
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 */
*/
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");
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;
}
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");
* 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) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
sock = -1;
continue;
}
if (ret) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
}
unlink(apps_unix_sock_path);
usess = session->ust_session;
if (session->enabled) {
- ret = LTTCOMM_UST_START_FAIL;
+ /* Already started. */
+ ret = LTTCOMM_TRACE_ALREADY_STARTED;
goto error;
}
usess = session->ust_session;
if (!session->enabled) {
- ret = LTTCOMM_UST_STOP_FAIL;
+ ret = LTTCOMM_TRACE_ALREADY_STOPPED;
goto 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;
}
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;
*/
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;
}
{
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:
unsigned int nr_sessions;
session_lock_list();
- nr_sessions = lttng_sessions_count(cmd_ctx->creds.uid, cmd_ctx->creds.gid);
+ 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) {
/* 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();
if (cmd_ctx->session) {
session_unlock(cmd_ctx->session);
}
+ if (need_tracing_session) {
+ session_unlock_list();
+ }
init_setup_error:
return ret;
}
PERROR("close");
}
sock = -1;
- free(cmd_ctx);
+ clean_command_ctx(&cmd_ctx);
continue;
}
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;
*/
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;
}
/*
*/
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;
}
/*
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 */
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" */
/*
/* 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) {
/* 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