X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=libust%2Flttng-ust-comm.c;h=037b314765ab12b6974f1ca26e294d1771fde504;hb=46050b1a32de8dd0a7b65347af630c4a77f433a1;hp=f676d1d81773058d151403ba3b0cd850e4a82414;hpb=d9e99d10f6c8e15484a14caa7fee3f1d25487edd;p=lttng-ust.git diff --git a/libust/lttng-ust-comm.c b/libust/lttng-ust-comm.c index f676d1d8..037b3147 100644 --- a/libust/lttng-ust-comm.c +++ b/libust/lttng-ust-comm.c @@ -23,52 +23,55 @@ #include #include #include -#include +#include +#include #include #include +#include -/* Socket from app (connect) to session daemon (listen) for communication */ -static int global_apps_socket = -1; -static char global_apps_sock_path[PATH_MAX] = DEFAULT_GLOBAL_APPS_UNIX_SOCK; -static pthread_t global_ust_listener; +/* + * 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; -/* TODO: allow global_apps_sock_path override */ +/* Should the ust comm thread quit ? */ +static int lttng_ust_comm_should_quit; -static int local_apps_socket = -1; -static char local_apps_sock_path[PATH_MAX]; -static pthread_t local_ust_listener; +/* + * Info about socket and associated listener thread. + */ +struct sock_info { + char sock_path[PATH_MAX]; + int socket; + pthread_t ust_listener; /* listener thread */ + int root_handle; +}; -static -int connect_global_apps_socket(void) -{ - int ret; +/* Socket from app (connect) to session daemon (listen) for communication */ +struct sock_info global_apps = { + .sock_path = DEFAULT_GLOBAL_APPS_UNIX_SOCK, + .socket = -1, + .root_handle = -1, +}; - ret = lttcomm_connect_unix_sock(global_apps_sock_path); - if (ret < 0) - return ret; - global_apps_socket = ret; +/* TODO: allow global_apps_sock_path override */ - return 0; -} +struct sock_info local_apps = { + .socket = -1, + .root_handle = -1, +}; static -int connect_local_apps_socket(void) +int setup_local_apps_socket(void) { const char *home_dir; - int ret; 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); - - ret = lttcomm_connect_unix_sock(local_apps_sock_path); - if (ret < 0) - return ret; - local_apps_socket = ret; - - return 0; } @@ -77,10 +80,14 @@ int register_app_to_sessiond(int socket) { ssize_t ret; struct { + uint32_t major; + uint32_t minor; pid_t pid; uid_t uid; } reg_msg; + reg_msg.major = LTTNG_UST_COMM_VERSION_MAJOR; + reg_msg.minor = LTTNG_UST_COMM_VERSION_MINOR; reg_msg.pid = getpid(); reg_msg.uid = getuid(); @@ -90,44 +97,182 @@ int register_app_to_sessiond(int socket) return ret; } +static +int send_reply(int sock, struct lttcomm_ust_reply *lur) +{ + ssize_t len; + + len = lttcomm_send_unix_sock(sock, lur, sizeof(*lur)); + switch (len) { + case sizeof(*lur): + DBG("message successfully sent"); + return 0; + 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; + } +} static -int parse_message(struct lttcomm_session_msg *lsm) +int handle_message(int sock, struct lttcomm_ust_msg *lum) { - switch (lsm->cmd_type) { - case LTTNG_CREATE_SESSION: - DBG("Handling create session message"); + int ret = 0; + const struct objd_ops *ops; + struct lttcomm_ust_reply lur; + pthread_mutex_lock(<tng_ust_comm_mutex); + memset(&lur, 0, sizeof(lur)); + + if (lttng_ust_comm_should_quit) { + ret = -EPERM; + goto end; + } + + ops = objd_ops(lum->handle); + if (!ops) { + ret = -ENOENT; + goto end; + } + + switch (lum->cmd) { + case LTTNG_UST_RELEASE: + if (lum->handle == LTTNG_UST_ROOT_HANDLE) + ret = -EPERM; + else + ret = objd_unref(lum->handle); break; default: - ERR("Unimplemented command %d", (int) lsm->cmd_type); - return -1; + if (ops->cmd) + ret = ops->cmd(lum->handle, lum->cmd, + (unsigned long) &lum->u); + else + ret = -ENOSYS; + break; } - return 0; + +end: + lur.handle = lum->handle; + lur.cmd = lum->cmd; + lur.ret_val = ret; + if (ret >= 0) { + lur.ret_code = LTTCOMM_OK; + } else { + lur.ret_code = LTTCOMM_SESSION_FAIL; + } + ret = send_reply(sock, &lur); + + pthread_mutex_unlock(<tng_ust_comm_mutex); + return ret; } static -void *ust_listener_thread(void *arg) +void cleanup_sock_info(struct sock_info *sock_info) { - int sock = *(int *) arg; int ret; + if (sock_info->socket != -1) { + ret = close(sock_info->socket); + if (ret) { + ERR("Error closing local apps socket"); + } + sock_info->socket = -1; + } + if (sock_info->root_handle != -1) { + ret = objd_unref(sock_info->root_handle); + if (ret) { + ERR("Error unref root handle"); + } + sock_info->root_handle = -1; + } +} + +/* + * 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) +{ + 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_info->sock_path); + if (ret < 0) { + ERR("Error connecting to global apps socket"); + pthread_mutex_unlock(<tng_ust_comm_mutex); + sleep(5); + goto restart; + } + + sock_info->socket = sock = ret; + + /* + * Create only one root handle per listener thread for the whole + * process lifetime. + */ + if (sock_info->root_handle == -1) { + ret = lttng_abi_create_root_handle(); + if (ret) { + ERR("Error creating root handle"); + pthread_mutex_unlock(<tng_ust_comm_mutex); + goto quit; + } + sock_info->root_handle = ret; + } + + ret = register_app_to_sessiond(sock); + if (ret < 0) { + ERR("Error registering app to local apps socket"); + pthread_mutex_unlock(<tng_ust_comm_mutex); + sleep(5); + goto restart; + } + pthread_mutex_unlock(<tng_ust_comm_mutex); + for (;;) { ssize_t len; - struct lttcomm_session_msg lsm; + struct lttcomm_ust_msg lum; - /* Receive session handle */ - len = lttcomm_recv_unix_sock(sock, &lsm, sizeof(lsm)); + len = lttcomm_recv_unix_sock(sock, &lum, sizeof(lum)); switch (len) { case 0: /* orderly shutdown */ DBG("ltt-sessiond has performed an orderly shutdown\n"); goto end; - case sizeof(lsm): + case sizeof(lum): DBG("message received\n"); - ret = parse_message(&lsm); - if (ret) { - ERR("Error parsing message\n"); + ret = handle_message(sock, &lum); + if (ret < 0) { + ERR("Error handling message\n"); } continue; case -1: @@ -143,6 +288,8 @@ void *ust_listener_thread(void *arg) } end: + goto restart; /* try to reconnect */ +quit: return NULL; } @@ -159,67 +306,53 @@ void __attribute__((constructor)) lttng_ust_comm_init(void) init_usterr(); -#if 0 - /* Connect to the global sessiond apps socket */ - ret = connect_global_apps_socket(); + ret = setup_local_apps_socket(); if (ret) { - ERR("Error connecting to global apps socket"); + ERR("Error setting up to local apps socket"); } +#if 0 + ret = pthread_create(&global_apps.ust_listener, NULL, + ust_listener_thread, &global_apps); #endif //0 - - /* Connect to the per-user (local) sessiond apps socket */ - ret = connect_local_apps_socket(); - if (ret) { - ERR("Error connecting to local apps socket"); - } - - if (global_apps_socket >= 0) { - ret = register_app_to_sessiond(global_apps_socket); - if (ret < 0) { - ERR("Error registering app to global apps socket"); - } - } - if (local_apps_socket >= 0) { - ret = register_app_to_sessiond(local_apps_socket); - if (ret < 0) { - ERR("Error registering app to local apps socket"); - } - ret = pthread_create(&local_ust_listener, NULL, - ust_listener_thread, &local_apps_socket); - } + ret = pthread_create(&local_apps.ust_listener, NULL, + ust_listener_thread, &local_apps); } void __attribute__((destructor)) lttng_ust_comm_exit(void) { int ret; + /* + * Using pthread_cancel here because: + * A) we don't want to hang application teardown. + * B) the thread is not allocating any resource. + */ + + /* + * 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 - ERR("dest %d", global_apps_socket); - if (global_apps_socket >= 0) { - ret = unregister_app_to_sessiond(global_apps_socket); - if (ret < 0) { - ERR("Error registering app to global apps socket"); - } - ret = close(global_apps_socket); - if (ret) { - ERR("Error closing global apps socket"); - } + ret = pthread_cancel(global_apps.ust_listener); + if (ret) { + ERR("Error cancelling global ust listener thread"); } -#endif - if (local_apps_socket >= 0) { - /* - * Using pthread_cancel here because: - * A) we don't want to hang application teardown. - * B) the thread is not allocating any resource. - */ - ret = pthread_cancel(local_ust_listener); - if (ret) { - ERR("Error joining local ust listener thread"); - } +#endif //0 - ret = close(local_apps_socket); - if (ret) { - ERR("Error closing local apps socket"); - } + cleanup_sock_info(&global_apps); + + ret = pthread_cancel(local_apps.ust_listener); + if (ret) { + ERR("Error cancelling local ust listener thread"); } + + cleanup_sock_info(&local_apps); + + lttng_ust_abi_exit(); + ltt_events_exit(); }