/* * Try connect to session daemon with sock_path. * * Return 0 on success, else -1 */ static int try_connect_sessiond(const char *sock_path) { int ret; /* If socket exist, we check if the daemon listens for connect. */ ret = access(sock_path, F_OK); if (ret < 0) { /* Not alive */ goto error; } ret = lttcomm_connect_unix_sock(sock_path); if (ret < 0) { /* Not alive */ goto error; } ret = lttcomm_close_unix_sock(ret); if (ret < 0) { PERROR("lttcomm_close_unix_sock"); } return 0; error: return -1; }
/* * Clean disconnect from the session daemon. * On success, return 0. On error, return -1. */ static int disconnect_sessiond(void) { int ret = 0; if (connected) { ret = lttcomm_close_unix_sock(sessiond_socket); sessiond_socket = 0; connected = 0; } return ret; }
void lttng_notification_channel_destroy( struct lttng_notification_channel *channel) { if (!channel) { return; } if (channel->socket >= 0) { (void) lttcomm_close_unix_sock(channel->socket); } pthread_mutex_destroy(&channel->lock); lttng_dynamic_buffer_reset(&channel->reception_buffer); free(channel); }
LTTNG_HIDDEN void run_as_destroy_worker(void) { struct run_as_worker *worker = global_worker; DBG("Destroying run_as worker"); pthread_mutex_lock(&worker_lock); if (!worker) { goto end; } /* Close unix socket */ DBG("Closing run_as worker socket"); if (lttcomm_close_unix_sock(worker->sockpair[0])) { PERROR("close"); } worker->sockpair[0] = -1; /* Wait for worker. */ for (;;) { int status; pid_t wait_ret; wait_ret = waitpid(worker->pid, &status, 0); if (wait_ret < 0) { if (errno == EINTR) { continue; } PERROR("waitpid"); break; } if (WIFEXITED(status)) { LOG(WEXITSTATUS(status) == 0 ? PRINT_DBG : PRINT_ERR, DEFAULT_RUN_AS_WORKER_NAME " terminated with status code %d", WEXITSTATUS(status)); break; } else if (WIFSIGNALED(status)) { ERR(DEFAULT_RUN_AS_WORKER_NAME " was killed by signal %d", WTERMSIG(status)); break; } } free(worker); global_worker = NULL; end: pthread_mutex_unlock(&worker_lock); }
static int run_as_create_worker_no_lock(const char *procname, post_fork_cleanup_cb clean_up_func, void *clean_up_user_data) { pid_t pid; int i, ret = 0; ssize_t readlen; struct run_as_ret recvret; struct run_as_worker *worker; assert(!global_worker); if (!use_clone()) { /* * Don't initialize a worker, all run_as tasks will be performed * in the current process. */ ret = 0; goto end; } worker = zmalloc(sizeof(*worker)); if (!worker) { ret = -ENOMEM; goto end; } worker->procname = strdup(procname); if (!worker->procname) { ret = -ENOMEM; goto error_procname_alloc; } /* Create unix socket. */ if (lttcomm_create_anon_unix_socketpair(worker->sockpair) < 0) { ret = -1; goto error_sock; } /* Fork worker. */ pid = fork(); if (pid < 0) { PERROR("fork"); ret = -1; goto error_fork; } else if (pid == 0) { /* Child */ reset_sighandler(); set_worker_sighandlers(); if (clean_up_func) { if (clean_up_func(clean_up_user_data) < 0) { ERR("Run-as post-fork clean-up failed, exiting."); exit(EXIT_FAILURE); } } /* Just close, no shutdown. */ if (close(worker->sockpair[0])) { PERROR("close"); exit(EXIT_FAILURE); } /* * Close all FDs aside from STDIN, STDOUT, STDERR and sockpair[1] * Sockpair[1] is used as a control channel with the master */ for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) { if (i != worker->sockpair[1]) { (void) close(i); } } worker->sockpair[0] = -1; ret = run_as_worker(worker); if (lttcomm_close_unix_sock(worker->sockpair[1])) { PERROR("close"); ret = -1; } worker->sockpair[1] = -1; free(worker->procname); free(worker); LOG(ret ? PRINT_ERR : PRINT_DBG, "run_as worker exiting (ret = %d)", ret); exit(ret ? EXIT_FAILURE : EXIT_SUCCESS); } else { /* Parent */ /* Just close, no shutdown. */ if (close(worker->sockpair[1])) { PERROR("close"); ret = -1; goto error_fork; } worker->sockpair[1] = -1; worker->pid = pid; /* Wait for worker to become ready. */ readlen = lttcomm_recv_unix_sock(worker->sockpair[0], &recvret, sizeof(recvret)); if (readlen < sizeof(recvret)) { ERR("readlen: %zd", readlen); PERROR("Error reading response from run_as at creation"); ret = -1; goto error_fork; } global_worker = worker; } end: return ret; /* Error handling. */ error_fork: for (i = 0; i < 2; i++) { if (worker->sockpair[i] < 0) { continue; } if (lttcomm_close_unix_sock(worker->sockpair[i])) { PERROR("close"); } worker->sockpair[i] = -1; } error_sock: free(worker->procname); error_procname_alloc: free(worker); return ret; }
LTTNG_HIDDEN int run_as_create_worker(char *procname) { pid_t pid; int i, ret = 0; ssize_t readlen; struct run_as_ret recvret; struct run_as_worker *worker; pthread_mutex_lock(&worker_lock); assert(!global_worker); if (!use_clone()) { /* * Don't initialize a worker, all run_as tasks will be performed * in the current process. */ ret = 0; goto end; } worker = zmalloc(sizeof(*worker)); if (!worker) { ret = -ENOMEM; goto end; } worker->procname = procname; /* Create unix socket. */ if (lttcomm_create_anon_unix_socketpair(worker->sockpair) < 0) { ret = -1; goto error_sock; } /* Fork worker. */ pid = fork(); if (pid < 0) { PERROR("fork"); ret = -1; goto error_fork; } else if (pid == 0) { /* Child */ reset_sighandler(); set_worker_sighandlers(); /* The child has no use for this lock. */ pthread_mutex_unlock(&worker_lock); /* Just close, no shutdown. */ if (close(worker->sockpair[0])) { PERROR("close"); exit(EXIT_FAILURE); } worker->sockpair[0] = -1; ret = run_as_worker(worker); if (lttcomm_close_unix_sock(worker->sockpair[1])) { PERROR("close"); ret = -1; } worker->sockpair[1] = -1; LOG(ret ? PRINT_ERR : PRINT_DBG, "run_as worker exiting (ret = %d)", ret); exit(ret ? EXIT_FAILURE : EXIT_SUCCESS); } else { /* Parent */ /* Just close, no shutdown. */ if (close(worker->sockpair[1])) { PERROR("close"); ret = -1; goto error_fork; } worker->sockpair[1] = -1; worker->pid = pid; /* Wait for worker to become ready. */ readlen = lttcomm_recv_unix_sock(worker->sockpair[0], &recvret, sizeof(recvret)); if (readlen < sizeof(recvret)) { ERR("readlen: %zd", readlen); PERROR("Error reading response from run_as at creation"); ret = -1; goto error_fork; } global_worker = worker; } end: pthread_mutex_unlock(&worker_lock); return ret; /* Error handling. */ error_fork: for (i = 0; i < 2; i++) { if (worker->sockpair[i] < 0) { continue; } if (lttcomm_close_unix_sock(worker->sockpair[i])) { PERROR("close"); } worker->sockpair[i] = -1; } error_sock: free(worker); pthread_mutex_unlock(&worker_lock); return ret; }