From 1ea11eab9f65504b2d217ef16f53f52ff941c630 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 23 Aug 2011 11:34:14 -0400 Subject: [PATCH] Session create/release tested. Signed-off-by: Mathieu Desnoyers --- include/lttng-ust-comm.h | 6 +- include/ust/lttng-tracer.h | 45 +++++++ include/ust/lttng-ust-abi.h | 3 + liblttng-ust-comm/lttng-ust-comm.c | 9 +- libust/ltt-events.c | 5 +- libust/lttng-ust-abi.c | 37 ++++-- libust/lttng-ust-comm.c | 182 +++++++++++++++++++++++------ tests/hello/hello.c | 1 + 8 files changed, 232 insertions(+), 56 deletions(-) create mode 100644 include/ust/lttng-tracer.h diff --git a/include/lttng-ust-comm.h b/include/lttng-ust-comm.h index 6914cc2a..b594367d 100644 --- a/include/lttng-ust-comm.h +++ b/include/lttng-ust-comm.h @@ -48,7 +48,6 @@ enum lttcomm_ust_command { UST_CREATE_SESSION, - UST_RELEASE_SESSION, UST_VERSION, UST_LIST_TRACEPOINTS, UST_WAIT_QUIESCENT, @@ -57,21 +56,18 @@ enum lttcomm_ust_command { /* Apply on session handle */ UST_METADATA, /* release with UST_RELEASE_CHANNEL */ UST_CHANNEL, - UST_RELEASE_CHANNEL, UST_SESSION_START, UST_SESSION_STOP, /* Apply on channel handle */ UST_STREAM, - UST_RELEASE_STREAM, UST_EVENT, - UST_RELEASE_EVENT, /* Apply on event and channel handle */ UST_CONTEXT, - UST_RELEASE_CONTEXT, /* Apply on event, channel and session handle */ + UST_RELEASE, UST_ENABLE, UST_DISABLE, }; diff --git a/include/ust/lttng-tracer.h b/include/ust/lttng-tracer.h new file mode 100644 index 00000000..18739e2d --- /dev/null +++ b/include/ust/lttng-tracer.h @@ -0,0 +1,45 @@ +#ifndef _LTTNG_TRACER_H +#define _LTTNG_TRACER_H + +/* + * Copyright (C) 2005-2011 Mathieu Desnoyers + * + * This contains the core definitions for the Linux Trace Toolkit. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS +/* Align data on its natural alignment */ +#define RING_BUFFER_ALIGN +#endif + +#define LTTNG_UST_VERSION 0 +#define LTTNG_UST_PATCHLEVEL 9 +#define LTTNG_UST_SUBLEVEL 1 + +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +#ifdef RING_BUFFER_ALIGN +#define lttng_alignof(type) __alignof__(type) +#else +#define lttng_alignof(type) 1 +#endif + +#define lttng_is_signed_type(type) (((type)(-1)) < 0) + +#endif /* _LTTNG_TRACER_CORE_H */ diff --git a/include/ust/lttng-ust-abi.h b/include/ust/lttng-ust-abi.h index 16c49d16..62f9d6cf 100644 --- a/include/ust/lttng-ust-abi.h +++ b/include/ust/lttng-ust-abi.h @@ -94,5 +94,8 @@ struct lttng_ust_context { #define LTTNG_UST_DISABLE _UST_CMD(0x81) void lttng_ust_abi_exit(void); +int lttng_abi_create_session(void); +int objd_unref(int id); +void ltt_events_exit(void); #endif /* _LTTNG_UST_ABI_H */ diff --git a/liblttng-ust-comm/lttng-ust-comm.c b/liblttng-ust-comm/lttng-ust-comm.c index 214f6e45..0ce9fc87 100644 --- a/liblttng-ust-comm/lttng-ust-comm.c +++ b/liblttng-ust-comm/lttng-ust-comm.c @@ -273,7 +273,14 @@ ssize_t lttcomm_send_unix_sock(int sock, void *buf, size_t len) msg.msg_iov = iov; msg.msg_iovlen = 1; - ret = sendmsg(sock, &msg, 0); + /* + * Using the MSG_NOSIGNAL when sending data from sessiond to + * libust, so libust does not receive an unhandled SIGPIPE or + * SIGURG. The sessiond receiver side can be made more resilient + * by ignoring SIGPIPE, but we don't have this luxury on the + * libust side. + */ + ret = sendmsg(sock, &msg, MSG_NOSIGNAL); if (ret < 0) { perror("sendmsg"); } diff --git a/libust/ltt-events.c b/libust/ltt-events.c index 8f9b7ed2..c99b6689 100644 --- a/libust/ltt-events.c +++ b/libust/ltt-events.c @@ -50,10 +50,10 @@ struct ltt_session *ltt_session_create(void) { struct ltt_session *session; - pthread_mutex_lock(&sessions_mutex); session = zmalloc(sizeof(struct ltt_session)); if (!session) return NULL; + pthread_mutex_lock(&sessions_mutex); CDS_INIT_LIST_HEAD(&session->chan); CDS_INIT_LIST_HEAD(&session->events); uuid_generate(session->uuid); @@ -870,8 +870,7 @@ void ltt_transport_unregister(struct ltt_transport *transport) pthread_mutex_unlock(&sessions_mutex); } -static -void __attribute__((destructor)) ltt_events_exit(void) +void ltt_events_exit(void) { struct ltt_session *session, *tmpsession; diff --git a/libust/lttng-ust-abi.c b/libust/lttng-ust-abi.c index fee3d075..dca010c9 100644 --- a/libust/lttng-ust-abi.c +++ b/libust/lttng-ust-abi.c @@ -153,11 +153,12 @@ void objd_ref(int id) obj->u.s.f_count++; } -static -void objd_unref(int id) +int objd_unref(int id) { struct obj *obj = _objd_get(id); + if (!obj) + return -EINVAL; if (!(--obj->u.s.f_count)) { const struct objd_ops *ops = objd_ops(id); @@ -165,6 +166,7 @@ void objd_unref(int id) ops->release(id); objd_free(id); } + return 0; } static @@ -189,7 +191,6 @@ enum channel_type { METADATA_CHANNEL, }; -static int lttng_abi_create_session(void) { struct ltt_session *session; @@ -396,7 +397,12 @@ int lttng_abi_create_channel(int session_objd, return chan_objd; chan_error: - objd_unref(chan_objd); + { + int err; + + err = objd_unref(chan_objd); + assert(!err); + } objd_error: return ret; } @@ -454,17 +460,20 @@ long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg) * individual file is released). */ static -int lttng_session_release(int objd) +int lttng_release_session(int objd) { struct ltt_session *session = objd_private(objd); - if (session) + if (session) { ltt_session_destroy(session); - return 0; + return 0; + } else { + return -EINVAL; + } } static const struct objd_ops lttng_session_ops = { - .release = lttng_session_release, + .release = lttng_release_session, .cmd = lttng_session_cmd, }; @@ -527,7 +536,12 @@ int lttng_abi_create_event(int channel_objd, return event_objd; event_error: - objd_unref(event_objd); + { + int err; + + err = objd_unref(event_objd); + assert(!err); + } objd_error: return ret; } @@ -639,7 +653,7 @@ int lttng_channel_release(int objd) struct ltt_channel *channel = objd_private(objd); if (channel) - objd_unref(channel->session->objd); + return objd_unref(channel->session->objd); return 0; } @@ -694,7 +708,7 @@ int lttng_event_release(int objd) struct ltt_event *event = objd_private(objd); if (event) - objd_unref(event->chan->objd); + return objd_unref(event->chan->objd); return 0; } @@ -706,6 +720,5 @@ static const struct objd_ops lttng_event_ops = { void lttng_ust_abi_exit(void) { - /* TODO: teardown socket */ objd_table_destroy(); } diff --git a/libust/lttng-ust-comm.c b/libust/lttng-ust-comm.c index c9cb7777..41d1280c 100644 --- a/libust/lttng-ust-comm.c +++ b/libust/lttng-ust-comm.c @@ -27,15 +27,37 @@ #include #include #include +#include + +/* + * communication thread mutex. Held when handling a command, also held + * by fork() to deal with removal of threads, and by exit path. + */ +static pthread_mutex_t lttng_ust_comm_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Should the ust comm thread quit ? */ +static int lttng_ust_comm_should_quit; + +/* + * Info about socket and associated listener thread. + */ +struct sock_info { + char sock_path[PATH_MAX]; + int socket; + pthread_t ust_listener; /* listener thread */ +}; /* Socket from app (connect) to session daemon (listen) for communication */ -static char global_apps_sock_path[PATH_MAX] = DEFAULT_GLOBAL_APPS_UNIX_SOCK; -static pthread_t global_ust_listener; +struct sock_info global_apps = { + .sock_path = DEFAULT_GLOBAL_APPS_UNIX_SOCK, + .socket = -1, +}; /* TODO: allow global_apps_sock_path override */ -static char local_apps_sock_path[PATH_MAX]; -static pthread_t local_ust_listener; +struct sock_info local_apps = { + .socket = -1, +}; static int setup_local_apps_socket(void) @@ -45,7 +67,7 @@ int setup_local_apps_socket(void) home_dir = (const char *) getenv("HOME"); if (!home_dir) return -ENOENT; - snprintf(local_apps_sock_path, PATH_MAX, + snprintf(local_apps.sock_path, PATH_MAX, DEFAULT_HOME_APPS_UNIX_SOCK, home_dir); return 0; } @@ -72,12 +94,18 @@ int register_app_to_sessiond(int socket) return ret; } - static int handle_message(int sock, struct lttcomm_ust_msg *lum) { ssize_t len; - int ret; + int ret = 0; + + pthread_mutex_lock(<tng_ust_comm_mutex); + + if (lttng_ust_comm_should_quit) { + ret = 0; + goto end; + } switch (lum->cmd_type) { case UST_CREATE_SESSION: @@ -88,56 +116,120 @@ int handle_message(int sock, struct lttcomm_ust_msg *lum) memset(&lur, 0, sizeof(lur)); lur.cmd_type = UST_CREATE_SESSION; - /* ... */ - ret = 0; - - if (!ret) + ret = lttng_abi_create_session(); + if (ret >= 0) { + lur.ret_val = ret; lur.ret_code = LTTCOMM_OK; - else + } else { lur.ret_code = LTTCOMM_SESSION_FAIL; - lur.ret_val = 42; + } len = lttcomm_send_unix_sock(sock, &lur, sizeof(lur)); switch (len) { case sizeof(lur): - printf("message successfully sent\n"); + DBG("message successfully sent"); break; case -1: if (errno == ECONNRESET) { printf("remote end closed connection\n"); - return 0; + ret = 0; + goto end; } - return -1; + ret = -1; + goto end; default: printf("incorrect message size: %zd\n", len); - return -1; + ret = -1; + goto end; + } + break; + } + case UST_RELEASE: + { + struct lttcomm_ust_reply lur; + + DBG("Handling release message, handle: %d", + lum->handle); + memset(&lur, 0, sizeof(lur)); + lur.cmd_type = UST_RELEASE; + + ret = objd_unref(lum->handle); + if (!ret) { + lur.ret_code = LTTCOMM_OK; + } else { + lur.ret_code = LTTCOMM_ERR; + } + len = lttcomm_send_unix_sock(sock, &lur, sizeof(lur)); + switch (len) { + case sizeof(lur): + DBG("message successfully sent\n"); + break; + case -1: + if (errno == ECONNRESET) { + printf("remote end closed connection\n"); + ret = 0; + goto end; + } + ret = -1; + goto end; + default: + printf("incorrect message size: %zd\n", len); + ret = -1; + goto end; } break; } default: ERR("Unimplemented command %d", (int) lum->cmd_type); - return -1; + ret = -1; + goto end; } - return 0; +end: + pthread_mutex_unlock(<tng_ust_comm_mutex); + return ret; } +/* + * This thread does not allocate any resource, except within + * handle_message, within mutex protection. This mutex protects against + * fork and exit. + * The other moment it allocates resources is at socket connexion, which + * is also protected by the mutex. + */ static void *ust_listener_thread(void *arg) { - const char *sock_path = (const char *) arg; - int sock; - int ret; + struct sock_info *sock_info = arg; + int sock, ret; /* Restart trying to connect to the session daemon */ restart: + pthread_mutex_lock(<tng_ust_comm_mutex); + + if (lttng_ust_comm_should_quit) { + pthread_mutex_unlock(<tng_ust_comm_mutex); + goto quit; + } + if (sock_info->socket != -1) { + ret = close(sock_info->socket); + if (ret) { + ERR("Error closing local apps socket"); + } + sock_info->socket = -1; + } /* Check for sessiond availability with pipe TODO */ /* Register */ - ret = lttcomm_connect_unix_sock(sock_path); + ret = lttcomm_connect_unix_sock(sock_info->sock_path); if (ret < 0) { ERR("Error connecting to global apps socket"); + pthread_mutex_unlock(<tng_ust_comm_mutex); + goto restart; + } else { + sock_info->socket = sock = ret; + pthread_mutex_unlock(<tng_ust_comm_mutex); } - sock = ret; + ret = register_app_to_sessiond(sock); if (ret < 0) { ERR("Error registering app to local apps socket"); @@ -174,11 +266,8 @@ restart: } end: - ret = close(sock); - if (ret) { - ERR("Error closing local apps socket"); - } goto restart; /* try to reconnect */ +quit: return NULL; } @@ -195,17 +284,16 @@ void __attribute__((constructor)) lttng_ust_comm_init(void) init_usterr(); - /* Connect to the per-user (local) sessiond apps socket */ ret = setup_local_apps_socket(); if (ret) { ERR("Error setting up to local apps socket"); } #if 0 - ret = pthread_create(&global_ust_listener, NULL, - ust_listener_thread, global_apps_sock_path); + ret = pthread_create(&global_apps.ust_listener, NULL, + ust_listener_thread, &global_apps); #endif //0 - ret = pthread_create(&local_ust_listener, NULL, - ust_listener_thread, local_apps_sock_path); + ret = pthread_create(&local_apps.ust_listener, NULL, + ust_listener_thread, &local_apps); } void __attribute__((destructor)) lttng_ust_comm_exit(void) @@ -217,13 +305,37 @@ void __attribute__((destructor)) lttng_ust_comm_exit(void) * A) we don't want to hang application teardown. * B) the thread is not allocating any resource. */ - ret = pthread_cancel(global_ust_listener); + + /* + * Require the communication thread to quit. Synchronize with + * mutexes to ensure it is not in a mutex critical section when + * pthread_cancel is later called. + */ + pthread_mutex_lock(<tng_ust_comm_mutex); + lttng_ust_comm_should_quit = 1; + pthread_mutex_unlock(<tng_ust_comm_mutex); + +#if 0 + ret = pthread_cancel(global_apps.ust_listener); if (ret) { ERR("Error cancelling global ust listener thread"); } - ret = pthread_cancel(local_ust_listener); +#endif //0 + if (global_apps.socket != -1) { + ret = close(global_apps.socket); + assert(!ret); + } + + ret = pthread_cancel(local_apps.ust_listener); if (ret) { ERR("Error cancelling local ust listener thread"); } + + if (local_apps.socket != -1) { + ret = close(local_apps.socket); + assert(!ret); + } + lttng_ust_abi_exit(); + ltt_events_exit(); } diff --git a/tests/hello/hello.c b/tests/hello/hello.c index 9cbe149b..e8eb78ef 100644 --- a/tests/hello/hello.c +++ b/tests/hello/hello.c @@ -40,6 +40,7 @@ int init_int_handler(void) int result; struct sigaction act; + memset(&act, 0, sizeof(act)); result = sigemptyset(&act.sa_mask); if (result == -1) { perror("sigemptyset"); -- 2.34.1