* Copyright (C) 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
*
- * 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 as published by
+ * the Free Software Foundation; version 2 of the License only.
*
- * 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 _LARGEFILE64_SOURCE
+#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <limits.h>
#include <assert.h>
#include <sys/socket.h>
-#include "lttng-ust-comm.h"
+#include <ust-comm.h>
+#include <lttng/ust-error.h>
#include "../../libringbuffer/backend.h"
#include "../../libringbuffer/frontend.h"
+#include "../../liblttng-ust/compat.h" /* For ENODATA */
#define MAX_NR_STREAMS 64
#define MAX_NR_EVENTS 128
-struct object_data {
- int handle;
- int shm_fd;
- int wait_fd;
- uint64_t memory_map_size;
-};
-
static int session_handle;
-static struct object_data metadata_stream_data;
-static struct object_data metadata_data;
-static struct object_data channel_data;
-static struct object_data stream_data[MAX_NR_STREAMS];
+static struct lttng_ust_object_data metadata_stream_data;
+static struct lttng_ust_object_data metadata_data;
+static struct lttng_ust_object_data channel_data;
+static struct lttng_ust_object_data stream_data[MAX_NR_STREAMS];
static int event_handle[MAX_NR_EVENTS];
+static int context_handle;
static int apps_socket = -1;
static char apps_sock_path[PATH_MAX];
quit_program = 1;
}
-static int send_app_msg(int sock, struct lttcomm_ust_msg *lum)
-{
- ssize_t len;
-
- len = lttcomm_send_unix_sock(sock, lum, sizeof(*lum));
- switch (len) {
- case sizeof(*lum):
- printf("message successfully sent\n");
- break;
- case -1:
- if (errno == ECONNRESET) {
- printf("remote end closed connection\n");
- return 0;
- }
- return -1;
- default:
- printf("incorrect message size: %zd\n", len);
- return -1;
- }
- return 0;
-}
-
-static int recv_app_reply(int sock, struct lttcomm_ust_reply *lur,
- uint32_t expected_handle, uint32_t expected_cmd)
-{
- ssize_t len;
-
- memset(lur, 0, sizeof(*lur));
- len = lttcomm_recv_unix_sock(sock, lur, sizeof(*lur));
- switch (len) {
- case 0: /* orderly shutdown */
- printf("Application has performed an orderly shutdown\n");
- return -EINVAL;
- case sizeof(*lur):
- printf("result message received\n");
- if (lur->handle != expected_handle) {
- printf("Unexpected result message handle\n");
- return -EINVAL;
- }
-
- if (lur->cmd != expected_cmd) {
- printf("Unexpected result message command\n");
- return -EINVAL;
- }
- if (lur->ret_code != LTTCOMM_OK) {
- printf("remote operation failed with code %d.\n",
- lur->ret_code);
- return lur->ret_code;
- }
- return 0;
- case -1:
- if (errno == ECONNRESET) {
- printf("remote end closed connection\n");
- return -EINVAL;
- }
- return -1;
- default:
- printf("incorrect message size: %zd\n", len);
- return len > 0 ? -1 : len;
- }
-}
-
-static int send_app_cmd(int sock,
- struct lttcomm_ust_msg *lum,
- struct lttcomm_ust_reply *lur)
-{
- int ret;
-
- ret = send_app_msg(sock, lum);
- if (ret)
- return ret;
- ret = recv_app_reply(sock, lur, lum->handle, lum->cmd);
- if (ret)
- return ret;
- return 0;
-}
-
-
-/*
- * Receives a single fd from socket.
- *
- * Returns the size of received data
- */
-static int lttcomm_recv_fd(int sock)
-{
- struct iovec iov[1];
- int ret = 0;
- int data_fd;
- struct cmsghdr *cmsg;
- char recv_fd[CMSG_SPACE(sizeof(int))];
- struct msghdr msg = { 0 };
- union {
- unsigned char vc[4];
- int vi;
- } tmp;
- int i;
-
- /* Prepare to receive the structures */
- iov[0].iov_base = &data_fd;
- iov[0].iov_len = sizeof(data_fd);
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_control = recv_fd;
- msg.msg_controllen = sizeof(recv_fd);
-
- printf("Waiting to receive fd\n");
- if ((ret = recvmsg(sock, &msg, 0)) < 0) {
- perror("recvmsg");
- goto end;
- }
- if (ret != sizeof(data_fd)) {
- printf("Received %d bytes, expected %ld", ret, sizeof(data_fd));
- goto end;
- }
- cmsg = CMSG_FIRSTHDR(&msg);
- if (!cmsg) {
- printf("Invalid control message header\n");
- ret = -1;
- goto end;
- }
- if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
- printf("Didn't received any fd\n");
- ret = -1;
- goto end;
- }
- /* this is our fd */
- for (i = 0; i < sizeof(int); i++)
- tmp.vc[i] = CMSG_DATA(cmsg)[i];
- ret = tmp.vi;
- printf("received fd %d\n", ret);
-end:
- return ret;
-}
-
-
static
-int open_streams(int sock, int channel_handle, struct object_data *stream_datas,
+int open_streams(int sock, int channel_handle, struct lttng_ust_object_data *stream_datas,
int nr_check)
{
int ret, k = 0;
for (;;) {
- struct lttcomm_ust_msg lum;
- struct lttcomm_ust_reply lur;
+ struct ustcomm_ust_msg lum;
+ struct ustcomm_ust_reply lur;
memset(&lum, 0, sizeof(lum));
lum.handle = channel_handle;
lum.cmd = LTTNG_UST_STREAM;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (!ret) {
assert(k < nr_check);
stream_datas[k].handle = lur.ret_val;
printf("received stream handle %u\n",
stream_datas[k].handle);
- if (lur.ret_code == LTTCOMM_OK) {
+ if (lur.ret_code == LTTNG_UST_OK) {
ssize_t len;
stream_datas[k].memory_map_size = lur.u.stream.memory_map_size;
/* get shm fd */
- len = lttcomm_recv_fd(sock);
+ len = ustcomm_recv_fd(sock);
if (len < 0)
return -EINVAL;
stream_datas[k].shm_fd = len;
/* get wait fd */
- len = lttcomm_recv_fd(sock);
+ len = ustcomm_recv_fd(sock);
if (len < 0)
return -EINVAL;
stream_datas[k].wait_fd = len;
}
k++;
}
- if (ret == -ENOENT)
+ if (ret == -LTTNG_UST_ERR_NOENT)
break;
if (ret)
return ret;
}
static
-int close_streams(int sock, struct object_data *stream_datas, int nr_check)
+int close_streams(int sock, struct lttng_ust_object_data *stream_datas, int nr_check)
{
int ret, k;
for (k = 0; k < nr_check; k++) {
- struct lttcomm_ust_msg lum;
- struct lttcomm_ust_reply lur;
+ struct ustcomm_ust_msg lum;
+ struct ustcomm_ust_reply lur;
if (!stream_datas[k].handle)
continue;
memset(&lum, 0, sizeof(lum));
lum.handle = stream_datas[k].handle;
lum.cmd = LTTNG_UST_RELEASE;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret) {
printf("Error closing stream\n");
return ret;
}
static
-struct shm_handle *map_channel(struct object_data *chan_data,
- struct object_data *stream_datas, int nr_check)
+struct lttng_ust_shm_handle *map_channel(struct lttng_ust_object_data *chan_data,
+ struct lttng_ust_object_data *stream_datas, int nr_check)
{
- struct shm_handle *handle;
+ struct lttng_ust_shm_handle *handle;
struct channel *chan;
int k, ret;
chan = shmp(handle, handle->chan);
for (k = 0; k < nr_check; k++) {
- struct object_data *stream_data = &stream_datas[k];
+ struct lttng_ust_object_data *stream_data = &stream_datas[k];
if (!stream_data->handle)
break;
}
static
-void unmap_channel(struct shm_handle *handle)
+void unmap_channel(struct lttng_ust_shm_handle *handle)
{
struct channel *chan;
}
static
-int consume_stream(struct shm_handle *handle, int cpu, char *outfile)
+int consume_stream(struct lttng_ust_shm_handle *handle, int cpu, char *outfile)
{
struct channel *chan;
- struct lib_ring_buffer *buf;
+ struct lttng_ust_lib_ring_buffer *buf;
int outfd, ret;
- int shm_fd, wait_fd;
- uint64_t memory_map_size;
+ int *shm_fd, *wait_fd;
+ uint64_t *memory_map_size;
chan = shmp(handle, handle->chan);
}
/* copy */
- outfd = open(outfile, O_WRONLY | O_CREAT | O_LARGEFILE | O_TRUNC,
+ outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (outfd < 0) {
perror("open output");
printf("WRITE: copy %lu bytes\n", read_size);
copy_size = write(outfd, ptr, read_size);
if (copy_size < read_size) {
- printf("write issue: copied %zd, expected %lu\n", copy_size, read_size);
+ printf("write issue: copied %lu, expected %lu\n", copy_size, read_size);
}
lib_ring_buffer_put_next_subbuf(buf, handle);
}
int k, ret;
mode_t old_umask;
char pathname[PATH_MAX];
- struct shm_handle *handle;
+ struct lttng_ust_shm_handle *handle;
snprintf(pathname, PATH_MAX - 1, "%s", outputpath);
old_umask = umask(0);
return 0;
}
+static
int send_app_msgs(int sock, const char *outputpath,
unsigned int nr_events, const char **event_names)
{
- struct lttcomm_ust_msg lum;
- struct lttcomm_ust_reply lur;
+ struct ustcomm_ust_msg lum;
+ struct ustcomm_ust_reply lur;
int ret, k;
/* Create session */
memset(&lum, 0, sizeof(lum));
lum.handle = LTTNG_UST_ROOT_HANDLE;
lum.cmd = LTTNG_UST_SESSION;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
session_handle = lur.ret_val;
lum.u.channel.switch_timer_interval = 0;
lum.u.channel.read_timer_interval = 0;
lum.u.channel.output = LTTNG_UST_MMAP;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
metadata_data.handle = lur.ret_val;
printf("received metadata handle %u\n", metadata_data.handle);
- if (lur.ret_code == LTTCOMM_OK) {
+ if (lur.ret_code == LTTNG_UST_OK) {
ssize_t len;
metadata_data.memory_map_size = lur.u.channel.memory_map_size;
/* get shm fd */
- len = lttcomm_recv_fd(sock);
+ len = ustcomm_recv_fd(sock);
if (len < 0)
return -EINVAL;
metadata_data.shm_fd = len;
/* get wait fd */
- len = lttcomm_recv_fd(sock);
+ len = ustcomm_recv_fd(sock);
if (len < 0)
return -EINVAL;
metadata_data.wait_fd = len;
lum.u.channel.switch_timer_interval = 0;
lum.u.channel.read_timer_interval = 0;
lum.u.channel.output = LTTNG_UST_MMAP;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
channel_data.handle = lur.ret_val;
printf("received channel handle %u\n", channel_data.handle);
- if (lur.ret_code == LTTCOMM_OK) {
+ if (lur.ret_code == LTTNG_UST_OK) {
ssize_t len;
channel_data.memory_map_size = lur.u.channel.memory_map_size;
/* get shm fd */
- len = lttcomm_recv_fd(sock);
+ len = ustcomm_recv_fd(sock);
if (len < 0)
return -EINVAL;
channel_data.shm_fd = len;
/* get wait fd */
- len = lttcomm_recv_fd(sock);
+ len = ustcomm_recv_fd(sock);
if (len < 0)
return -EINVAL;
channel_data.wait_fd = len;
strncpy(lum.u.event.name, event_names[k],
LTTNG_UST_SYM_NAME_LEN);
lum.u.event.instrumentation = LTTNG_UST_TRACEPOINT;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
event_handle[k] = lur.ret_val;
printf("received event handle %u\n", event_handle[k]);
}
+ /* Attach vtid context */
+ memset(&lum, 0, sizeof(lum));
+ lum.handle = channel_data.handle;
+ lum.cmd = LTTNG_UST_CONTEXT;
+ lum.u.context.ctx = LTTNG_UST_CONTEXT_VTID;
+ //lum.u.context.ctx = LTTNG_UST_CONTEXT_PTHREAD_ID;
+ //lum.u.context.ctx = LTTNG_UST_CONTEXT_VPID;
+ //lum.u.context.ctx = LTTNG_UST_CONTEXT_PROCNAME;
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+ if (ret)
+ return ret;
+ context_handle = lur.ret_val;
+ printf("received context handle %u\n", context_handle);
+
/* Get references to channel streams */
ret = open_streams(sock, channel_data.handle,
stream_data, MAX_NR_STREAMS);
memset(&lum, 0, sizeof(lum));
lum.handle = session_handle;
lum.cmd = LTTNG_UST_SESSION_START;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
printf("Session handle %u started.\n", session_handle);
memset(&lum, 0, sizeof(lum));
lum.handle = LTTNG_UST_ROOT_HANDLE;
lum.cmd = LTTNG_UST_REGISTER_DONE;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
printf("Registration done acknowledged.\n");
if (ret)
return ret;
+ /* Release context */
+ memset(&lum, 0, sizeof(lum));
+ lum.handle = context_handle;
+ lum.cmd = LTTNG_UST_RELEASE;
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+ if (ret)
+ return ret;
+
/* Release events */
for (k = 0; k < nr_events; k++) {
memset(&lum, 0, sizeof(lum));
lum.handle = event_handle[k];
lum.cmd = LTTNG_UST_RELEASE;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
}
memset(&lum, 0, sizeof(lum));
lum.handle = channel_data.handle;
lum.cmd = LTTNG_UST_RELEASE;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
if (channel_data.shm_fd >= 0) {
memset(&lum, 0, sizeof(lum));
lum.handle = metadata_data.handle;
lum.cmd = LTTNG_UST_RELEASE;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
if (metadata_data.shm_fd >= 0) {
memset(&lum, 0, sizeof(lum));
lum.handle = session_handle;
lum.cmd = LTTNG_UST_RELEASE;
- ret = send_app_cmd(sock, &lum, &lur);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
int update_futex(int fd, int active)
{
- size_t mmap_size = sysconf(_SC_PAGE_SIZE);
+ long page_size;
char *wait_shm_mmap;
int ret;
- wait_shm_mmap = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
+ page_size = sysconf(_SC_PAGE_SIZE);
+ if (page_size <= 0) {
+ if (!page_size) {
+ errno = EINVAL;
+ }
+ perror("Error in sysconf(_SC_PAGE_SIZE)");
+ goto error;
+ }
+ wait_shm_mmap = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (wait_shm_mmap == MAP_FAILED) {
perror("mmap");
if (active) {
uatomic_set((int32_t *) wait_shm_mmap, 1);
- futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE,
- INT_MAX, NULL, NULL, 0);
+ if (futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE,
+ INT_MAX, NULL, NULL, 0) < 0) {
+ perror("futex_async");
+ goto error;
+ }
} else {
uatomic_set((int32_t *) wait_shm_mmap, 0);
}
- ret = munmap(wait_shm_mmap, mmap_size);
+ ret = munmap(wait_shm_mmap, page_size);
if (ret) {
perror("Error unmapping wait shm");
goto error;
int main(int argc, const char **argv)
{
const char *home_dir;
+ char home_rundir[PATH_MAX];
+ char *cmd = NULL;
int ret, wait_shm_fd;
struct sigaction act;
mode_t old_umask = 0;
const char *outputpath;
const char **event_names;
unsigned int nr_events;
+ long page_size;
if (argc < 2) {
printf("Usage:\n");
return -1;
}
+ page_size = sysconf(_SC_PAGE_SIZE);
+ if (page_size <= 0) {
+ if (!page_size) {
+ errno = EINVAL;
+ }
+ perror("Error in sysconf(_SC_PAGE_SIZE)");
+ return -1;
+ }
+
if (geteuid() == 0) {
ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (ret && errno != EEXIST) {
return -1;
}
wait_shm_fd = get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
- sysconf(_SC_PAGE_SIZE), 1);
+ page_size, 1);
if (wait_shm_fd < 0) {
perror("global wait shm error");
return -1;
strcpy(apps_sock_path, DEFAULT_GLOBAL_APPS_UNIX_SOCK);
old_umask = umask(0);
} else {
+ home_dir = (const char *) getenv("HOME");
+ if (!home_dir) {
+ perror("getenv error");
+ return -ENOENT;
+ }
+
+ snprintf(home_rundir, PATH_MAX,
+ LTTNG_HOME_RUNDIR, home_dir);
+
+ ret = mkdir(home_rundir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ if (ret && errno != EEXIST) {
+ perror("mkdir");
+ return -1;
+ }
+
snprintf(local_apps_wait_shm_path, PATH_MAX,
DEFAULT_HOME_APPS_WAIT_SHM_PATH, getuid());
wait_shm_fd = get_wait_shm(local_apps_wait_shm_path,
- sysconf(_SC_PAGE_SIZE), 0);
+ page_size, 0);
if (wait_shm_fd < 0) {
perror("local wait shm error");
return -1;
}
- home_dir = (const char *) getenv("HOME");
- if (!home_dir) {
- perror("getenv error");
- return -ENOENT;
- }
snprintf(apps_sock_path, PATH_MAX,
DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
}
- ret = lttcomm_create_unix_sock(apps_sock_path);
+ ret = ustcomm_create_unix_sock(apps_sock_path);
if (ret < 0) {
perror("create error");
return ret;
}
umask(old_umask);
}
- ret = lttcomm_listen_unix_sock(apps_socket);
+ ret = ustcomm_listen_unix_sock(apps_socket);
if (ret < 0) {
perror("listen error");
return ret;
pid_t ppid;
uid_t uid;
gid_t gid;
+ uint32_t bits_per_long;
char name[16]; /* Process name */
} reg_msg;
char bufname[17];
break;
printf("Accepting application registration\n");
- sock = lttcomm_accept_unix_sock(apps_socket);
+ sock = ustcomm_accept_unix_sock(apps_socket);
if (sock < 0) {
perror("accept error");
goto end;
* Basic recv here to handle the very simple data
* that the libust send to register (reg_msg).
*/
- len = lttcomm_recv_unix_sock(sock, ®_msg, sizeof(reg_msg));
+ len = ustcomm_recv_unix_sock(sock, ®_msg, sizeof(reg_msg));
if (len < 0 || len != sizeof(reg_msg)) {
- perror("lttcomm_recv_unix_sock");
+ perror("ustcomm_recv_unix_sock");
continue;
}
memcpy(bufname, reg_msg.name, 16);
return -1;
}
+ if (geteuid()) {
+ printf("Removing %s directory\n", home_rundir);
+ ret = asprintf(&cmd, "rm -rf %s", home_rundir);
+ if (ret < 0) {
+ printf("asprintf failed. Something is really wrong!\n");
+ return -1;
+ }
+
+ /* Remove lttng run directory */
+ ret = system(cmd);
+ if (ret < 0) {
+ printf("Unable to clean %s\n", home_rundir);
+ return -1;
+ }
+ }
+
+
return 0;
}