shm.c shm.h \
session.c session.h \
modprobe.c modprobe.h kern-modules.h \
- lttng-ust-ctl.h lttng-ust-abi.h
+ lttng-ust-ctl.h lttng-ust-abi.h \
+ fd-limit.c fd-limit.h
if HAVE_LIBLTTNG_UST_CTL
lttng_sessiond_SOURCES += trace-ust.c ust-app.c ust-consumer.c ust-consumer.h
--- /dev/null
+/*
+ * Copyright (C) 2012 - 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, 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.
+ *
+ * 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 <urcu/uatomic.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <errno.h>
+#include <stdio.h>
+#include "fd-limit.h"
+
+/* total count of fd. */
+static long fd_count;
+
+/*
+ * threshold in % of number of fd allowed.
+ */
+static long fd_threshold[LTTNG_FD_NR_TYPES] = {
+ [LTTNG_FD_APPS] = 75,
+};
+
+static rlim_t max_nr_fd;
+
+int lttng_fd_get(enum lttng_fd_type type, unsigned int nr)
+{
+ long newval;
+
+ if (type >= LTTNG_FD_NR_TYPES) {
+ return -EINVAL;
+ }
+
+ newval = uatomic_add_return(&fd_count, (long) nr);
+ if ((long) (newval * 100)
+ - (long) (max_nr_fd * fd_threshold[type]) > 0) {
+ uatomic_sub(&fd_count, (long) nr);
+ return -EPERM;
+ }
+ return 0;
+}
+
+void lttng_fd_put(enum lttng_fd_type type, unsigned int nr)
+{
+ uatomic_sub(&fd_count, (long) nr);
+}
+
+void lttng_fd_init(void)
+{
+ struct rlimit rlim;
+ int ret;
+
+ ret = getrlimit(RLIMIT_NOFILE, &rlim);
+ if (ret < 0) {
+ perror("getrlimit");
+ }
+ max_nr_fd = rlim.rlim_cur;
+}
--- /dev/null
+#ifndef _LTTNG_FD_LIMIT_H
+#define _LTTNG_FD_LIMIT_H
+
+/*
+ * Copyright (C) 2012 - 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, 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.
+ *
+ * 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.
+ */
+
+enum lttng_fd_type {
+ LTTNG_FD_APPS,
+ LTTNG_FD_NR_TYPES,
+};
+
+int lttng_fd_get(enum lttng_fd_type type, unsigned int nr);
+void lttng_fd_put(enum lttng_fd_type type, unsigned int nr);
+void lttng_fd_init(void);
+
+#endif /* _LTTNG_FD_LIMIT_H */
#include "shm.h"
#include "ust-ctl.h"
#include "utils.h"
+#include "fd-limit.h"
#define CONSUMERD_FILE "lttng-consumerd"
* 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);
/* 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) {
#include "ust-app.h"
#include "ust-consumer.h"
#include "ust-ctl.h"
+#include "fd-limit.h"
/*
* Delete ust context safely. RCU read lock must be held before calling
{
if (stream->obj) {
ustctl_release_object(sock, stream->obj);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(stream->obj);
}
free(stream);
if (ua_chan->obj != NULL) {
ustctl_release_object(sock, ua_chan->obj);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(ua_chan->obj);
}
free(ua_chan);
if (ua_sess->metadata) {
if (ua_sess->metadata->stream_obj) {
ustctl_release_object(sock, ua_sess->metadata->stream_obj);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(ua_sess->metadata->stream_obj);
}
if (ua_sess->metadata->obj) {
ustctl_release_object(sock, ua_sess->metadata->obj);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(ua_sess->metadata->obj);
}
trace_ust_destroy_metadata(ua_sess->metadata);
if (ret) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
DBG2("UST app pid %d deleted", app->pid);
free(app);
ua_sess->metadata->attr.read_timer_interval;
uattr.output = ua_sess->metadata->attr.output;
+ /* We are going to receive 2 fds, we need to reserve them. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon metadata open");
+ goto error;
+ }
/* UST tracer metadata creation */
ret = ustctl_open_metadata(app->sock, ua_sess->handle, &uattr,
&ua_sess->metadata->obj);
{
int ret;
+ /* We are going to receive 2 fds, we need to reserve them. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon metadata stream create");
+ goto error;
+ }
ret = ustctl_create_stream(app->sock, ua_sess->metadata->obj,
&ua_sess->metadata->stream_obj);
if (ret < 0) {
int ret;
/* TODO: remove cast and use lttng-ust-abi.h */
+
+ /* We are going to receive 2 fds, we need to reserve them. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon create channel");
+ goto error;
+ }
ret = ustctl_create_channel(app->sock, ua_sess->handle,
(struct lttng_ust_channel_attr *)&ua_chan->attr, &ua_chan->obj);
if (ret < 0) {
"and session handle %d with ret %d",
ua_chan->name, app->pid, app->sock,
ua_sess->handle, ret);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
goto error;
}
if (ret) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
return -EINVAL;
}
if (msg->major != LTTNG_UST_COMM_MAJOR) {
if (ret) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
return -EINVAL;
}
lta = zmalloc(sizeof(struct ust_app));
goto error_rcu_unlock;
}
+ /* We are going to receive 2 fds, we need to reserve them. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon stream create");
+ free(ustream);
+ goto error_rcu_unlock;
+ }
ret = ustctl_create_stream(app->sock, ua_chan->obj,
&ustream->obj);
if (ret < 0) {
/* Got all streams */
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(ustream);
break;
}