}
}
+static void stop_threads(void)
+{
+ /* Stopping all threads */
+ DBG("Terminating all threads");
+ close(thread_quit_pipe[0]);
+ close(thread_quit_pipe[1]);
+}
+
/*
* Cleanup the daemon
*/
-static void cleanup()
+static void cleanup(void)
{
int ret;
char *cmd;
27, 1, 31, 27, 0, 27, 1, 33, 27, 0);
/* </fun> */
- /* Stopping all threads */
- DBG("Terminating all threads");
- close(thread_quit_pipe[0]);
- close(thread_quit_pipe[1]);
-
DBG("Removing %s directory", LTTNG_RUNDIR);
ret = asprintf(&cmd, "rm -rf " LTTNG_RUNDIR);
if (ret < 0) {
return ret;
}
+static int join_kconsumerd_thread(void)
+{
+ void *status;
+ int ret;
+
+ if (kconsumerd_pid != 0) {
+ ret = kill(kconsumerd_pid, SIGTERM);
+ if (ret) {
+ ERR("Error killing kconsumerd");
+ return ret;
+ }
+ return pthread_join(kconsumerd_thread, &status);
+ } else {
+ return 0;
+ }
+}
+
/*
* Fork and exec a kernel consumer daemon (kconsumerd).
*
* apps_sock - The communication socket for all UST apps.
* client_sock - The communication of the cli tool (lttng).
*/
-static int init_daemon_socket()
+static int init_daemon_socket(void)
{
int ret = 0;
mode_t old_umask;
/*
* Check if the global socket is available. If yes, error is returned.
*/
-static int check_existing_daemon()
+static int check_existing_daemon(void)
{
int ret;
/*
* Signal handler for the daemon
+ *
+ * Simply stop all worker threads, leaving main() return gracefully
+ * after joining all threads and calling cleanup().
*/
static void sighandler(int sig)
{
switch (sig) {
- case SIGPIPE:
- DBG("SIGPIPE catched");
- return;
- case SIGINT:
- DBG("SIGINT catched");
- cleanup();
- break;
- case SIGTERM:
- DBG("SIGTERM catched");
- cleanup();
- break;
- default:
- break;
+ case SIGPIPE:
+ DBG("SIGPIPE catched");
+ return;
+ case SIGINT:
+ DBG("SIGINT catched");
+ stop_threads();
+ break;
+ case SIGTERM:
+ DBG("SIGTERM catched");
+ stop_threads();
+ break;
+ default:
+ break;
}
-
- exit(EXIT_SUCCESS);
}
/*
const char *home_path;
/* Create thread quit pipe */
- if (init_thread_quit_pipe() < 0) {
- goto exit;
+ if ((ret = init_thread_quit_pipe()) < 0) {
+ goto error;
}
/* Parse arguments */
progname = argv[0];
if ((ret = parse_args(argc, argv) < 0)) {
- goto exit;
+ goto error;
}
/* Daemonize */
ret = daemon(0, 0);
if (ret < 0) {
perror("daemon");
- goto exit;
+ goto error;
}
}
if (is_root) {
ret = create_lttng_rundir();
if (ret < 0) {
- goto exit;
+ goto error;
}
if (strlen(apps_unix_sock_path) == 0) {
if (home_path == NULL) {
/* TODO: Add --socket PATH option */
ERR("Can't get HOME directory for sockets creation.");
- goto exit;
+ ret = -EPERM;
+ goto error;
}
if (strlen(apps_unix_sock_path) == 0) {
if ((ret = check_existing_daemon()) == 0) {
ERR("Already running daemon.\n");
/*
- * We do not goto error because we must not cleanup() because a daemon
- * is already running.
+ * We do not goto exit because we must not cleanup()
+ * because a daemon is already running.
*/
- goto exit;
+ goto error;
}
/* After this point, we can safely call cleanup() so goto error is used */
if (is_root) {
ret = set_kconsumerd_sockets();
if (ret < 0) {
- goto error;
+ goto exit;
}
/* Setup kernel tracer */
set_ulimit();
}
- if (set_signal_handler() < 0) {
- goto error;
+ if ((ret = set_signal_handler()) < 0) {
+ goto exit;
}
/* Setup the needed unix socket */
- if (init_daemon_socket() < 0) {
- goto error;
+ if ((ret = init_daemon_socket()) < 0) {
+ goto exit;
}
/* Set credentials to socket */
- if (is_root && (set_permissions() < 0)) {
- goto error;
+ if (is_root && ((ret = set_permissions()) < 0)) {
+ goto exit;
}
/* Get parent pid if -S, --sig-parent is specified. */
}
/* Setup the kernel pipe for waking up the kernel thread */
- if (create_kernel_poll_pipe() < 0) {
- goto error;
+ if ((ret = create_kernel_poll_pipe()) < 0) {
+ goto exit;
}
/*
*/
session_list_ptr = get_session_list();
- while (1) {
- /* Create thread to manage the client socket */
- ret = pthread_create(&client_thread, NULL, thread_manage_clients, (void *) NULL);
- if (ret != 0) {
- perror("pthread_create");
- goto error;
- }
+ /* Create thread to manage the client socket */
+ ret = pthread_create(&client_thread, NULL, thread_manage_clients, (void *) NULL);
+ if (ret != 0) {
+ perror("pthread_create");
+ goto exit_client;
+ }
- /* Create thread to manage application socket */
- ret = pthread_create(&apps_thread, NULL, thread_manage_apps, (void *) NULL);
- if (ret != 0) {
- perror("pthread_create");
- goto error;
- }
+ /* Create thread to manage application socket */
+ ret = pthread_create(&apps_thread, NULL, thread_manage_apps, (void *) NULL);
+ if (ret != 0) {
+ perror("pthread_create");
+ goto exit_apps;
+ }
- /* Create kernel thread to manage kernel event */
- ret = pthread_create(&kernel_thread, NULL, thread_manage_kernel, (void *) NULL);
- if (ret != 0) {
- perror("pthread_create");
- goto error;
- }
+ /* Create kernel thread to manage kernel event */
+ ret = pthread_create(&kernel_thread, NULL, thread_manage_kernel, (void *) NULL);
+ if (ret != 0) {
+ perror("pthread_create");
+ goto exit_kernel;
+ }
- ret = pthread_join(client_thread, &status);
- if (ret != 0) {
- perror("pthread_join");
- goto error;
- }
+ ret = pthread_join(kernel_thread, &status);
+ if (ret != 0) {
+ perror("pthread_join");
+ goto error; /* join error, exit without cleanup */
}
- cleanup();
- exit(EXIT_SUCCESS);
+exit_kernel:
+ ret = pthread_join(apps_thread, &status);
+ if (ret != 0) {
+ perror("pthread_join");
+ goto error; /* join error, exit without cleanup */
+ }
-error:
- cleanup();
+exit_apps:
+ ret = pthread_join(client_thread, &status);
+ if (ret != 0) {
+ perror("pthread_join");
+ goto error; /* join error, exit without cleanup */
+ }
+
+ ret = join_kconsumerd_thread();
+ if (ret != 0) {
+ perror("join_kconsumerd");
+ goto error; /* join error, exit without cleanup */
+ }
+exit_client:
exit:
+ /*
+ * cleanup() is called when no other thread is running.
+ */
+ cleanup();
+ if (!ret)
+ exit(EXIT_SUCCESS);
+error:
exit(EXIT_FAILURE);
}