wait_queue->count--;
ust_app_destroy(wait_node->app);
free(wait_node);
+ /*
+ * Silence warning of use-after-free in
+ * cds_list_for_each_entry_safe which uses
+ * __typeof__(*wait_node).
+ */
+ wait_node = NULL;
break;
}
}
* Don't care about return value. Let the manage apps threads
* handle app unregistration upon socket close.
*/
- (void) ust_app_register_done(app->sock);
+ (void) ust_app_register_done(app);
/*
* Even if the application socket has been closed, send the app
free(wait_node);
}
+ /* Empty command queue. */
+ for (;;) {
+ /* Dequeue command for registration */
+ node = cds_wfcq_dequeue_blocking(&ust_cmd_queue.head, &ust_cmd_queue.tail);
+ if (node == NULL) {
+ break;
+ }
+ ust_cmd = caa_container_of(node, struct ust_command, node);
+ ret = close(ust_cmd->sock);
+ if (ret < 0) {
+ PERROR("close ust sock exit dispatch %d", ust_cmd->sock);
+ }
+ lttng_fd_put(LTTNG_FD_APPS, 1);
+ free(ust_cmd);
+ }
+
error_testpoint:
DBG("Dispatch thread dying");
if (err) {
}
exit_reg_apps:
+ /*
+ * Join dispatch thread after joining reg_apps_thread to ensure
+ * we don't leak applications in the queue.
+ */
ret = pthread_join(dispatch_thread, &status);
if (ret) {
errno = ret;
sessiond_cleanup_options();
exit_set_signal_handler:
+ /* Ensure all prior call_rcu are done. */
+ rcu_barrier();
+
if (!retval) {
exit(EXIT_SUCCESS);
} else {