/*
- * Copyright (C) 2011 - Julien Desfossez <julien.desfossez@polymtl.ca>
- * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2 only,
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier: GPL-2.0-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.
- *
- * 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 _LGPL_SOURCE
static pthread_t channel_thread, data_thread, metadata_thread,
sessiond_thread, metadata_timer_thread, health_thread;
+static bool metadata_timer_thread_online;
/* to count the number of times the user pressed ctrl+c */
static int sigintcount = 0;
lttng_opt_quiet = 1;
break;
case 'v':
- lttng_opt_verbose = 1;
+ lttng_opt_verbose = 3;
break;
case 'V':
fprintf(stdout, "%s\n", VERSION);
void *status;
struct lttng_consumer_local_data *tmp_ctx;
+ rcu_register_thread();
+
+ if (run_as_create_worker(argv[0], NULL, NULL) < 0) {
+ goto exit_set_signal_handler;
+ }
+
if (set_signal_handler()) {
retval = -1;
goto exit_set_signal_handler;
set_ulimit();
}
- if (run_as_create_worker(argv[0]) < 0) {
- goto exit_init_data;
- }
-
/* create the consumer instance with and assign the callbacks */
ctx = lttng_consumer_create(opt_type, lttng_consumer_read_subbuffer,
NULL, lttng_consumer_on_recv_stream, NULL);
}
cmm_smp_mb(); /* Read ready before following operations */
+ /*
+ * Create the thread to manage the UST metadata periodic timer and
+ * live timer.
+ */
+ ret = pthread_create(&metadata_timer_thread, NULL,
+ consumer_timer_thread, (void *) ctx);
+ if (ret) {
+ errno = ret;
+ PERROR("pthread_create");
+ retval = -1;
+ goto exit_metadata_timer_thread;
+ }
+ metadata_timer_thread_online = true;
+
/* Create thread to manage channels */
ret = pthread_create(&channel_thread, default_pthread_attr(),
consumer_thread_channel_poll,
goto exit_data_thread;
}
- /* Create the thread to manage the receive of fd */
+ /* Create the thread to manage the reception of fds */
ret = pthread_create(&sessiond_thread, default_pthread_attr(),
consumer_thread_sessiond_poll,
(void *) ctx);
goto exit_sessiond_thread;
}
- /*
- * Create the thread to manage the UST metadata periodic timer and
- * live timer.
- */
- ret = pthread_create(&metadata_timer_thread, default_pthread_attr(),
- consumer_timer_thread, (void *) ctx);
- if (ret) {
- errno = ret;
- PERROR("pthread_create");
- retval = -1;
- goto exit_metadata_timer_thread;
- }
-
- ret = pthread_detach(metadata_timer_thread);
- if (ret) {
- errno = ret;
- PERROR("pthread_detach");
- retval = -1;
- goto exit_metadata_timer_detach;
- }
/*
* This is where we start awaiting program completion (e.g. through
* signal that asks threads to teardown.
*/
-exit_metadata_timer_detach:
-exit_metadata_timer_thread:
ret = pthread_join(sessiond_thread, &status);
if (ret) {
errno = ret;
}
exit_channel_thread:
+exit_metadata_timer_thread:
+
ret = pthread_join(health_thread, &status);
if (ret) {
errno = ret;
exit_health_pipe:
exit_init_data:
- tmp_ctx = ctx;
- ctx = NULL;
- cmm_barrier(); /* Clear ctx for signal handler. */
/*
* Wait for all pending call_rcu work to complete before tearing
* down data structures. call_rcu worker may be trying to
* perform lookups in those structures.
*/
rcu_barrier();
- lttng_consumer_destroy(tmp_ctx);
lttng_consumer_cleanup();
+ /*
+ * Tearing down the metadata timer thread in a
+ * non-fully-symmetric fashion compared to its creation in case
+ * lttng_consumer_cleanup() ends up tearing down timers (which
+ * requires the timer thread to be alive).
+ */
+ if (metadata_timer_thread_online) {
+ /*
+ * Ensure the metadata timer thread exits only after all other
+ * threads are gone, because it is required to perform timer
+ * teardown synchronization.
+ */
+ kill(getpid(), LTTNG_CONSUMER_SIG_EXIT);
+ ret = pthread_join(metadata_timer_thread, &status);
+ if (ret) {
+ errno = ret;
+ PERROR("pthread_join metadata_timer_thread");
+ retval = -1;
+ }
+ ret = consumer_timer_thread_get_channel_monitor_pipe();
+ if (ret >= 0) {
+ ret = close(ret);
+ if (ret) {
+ PERROR("close channel monitor pipe");
+ }
+ }
+ metadata_timer_thread_online = false;
+ }
+ tmp_ctx = ctx;
+ ctx = NULL;
+ cmm_barrier(); /* Clear ctx for signal handler. */
+ lttng_consumer_destroy(tmp_ctx);
if (health_consumerd) {
health_app_destroy(health_consumerd);
exit_options:
exit_set_signal_handler:
+ rcu_unregister_thread();
+
if (!retval) {
exit(EXIT_SUCCESS);
} else {