Bug #539 » bug539.diff
| src/bin/lttng-sessiond/lttng-sessiond.h | ||
|---|---|---|
|
};
|
||
|
/*
|
||
|
* Use by the dispatch registration to queue UST command socket to wait for the
|
||
|
* notify socket.
|
||
|
*/
|
||
|
struct ust_reg_wait_node {
|
||
|
struct ust_app *app;
|
||
|
struct cds_list_head head;
|
||
|
};
|
||
|
/*
|
||
|
* This pipe is used to inform the thread managing application notify
|
||
|
* communication that a command is queued and ready to be processed.
|
||
|
*/
|
||
| src/bin/lttng-sessiond/main.c | ||
|---|---|---|
|
}
|
||
|
/*
|
||
|
* Sanitize the wait queue of the dispatch registration thread meaning removing
|
||
|
* invalid nodes from it. This is to avoid memory leaks for the case the UST
|
||
|
* notify socket is never received.
|
||
|
*/
|
||
|
void sanitize_wait_queue(struct cds_list_head *wait_queue)
|
||
|
{
|
||
|
int ret, nb_fd = 0, i;
|
||
|
unsigned int fd_added = 0;
|
||
|
struct lttng_poll_event events;
|
||
|
struct ust_reg_wait_node *wait_node = NULL, *tmp_wait_node;
|
||
|
assert(wait_queue);
|
||
|
lttng_poll_init(&events);
|
||
|
ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
|
||
|
if (ret < 0) {
|
||
|
goto error_create;
|
||
|
}
|
||
|
cds_list_for_each_entry_safe(wait_node, tmp_wait_node,
|
||
|
wait_queue, head) {
|
||
|
assert(wait_node->app);
|
||
|
ret = lttng_poll_add(&events, wait_node->app->sock,
|
||
|
LPOLLHUP | LPOLLERR);
|
||
|
if (ret < 0) {
|
||
|
goto error;
|
||
|
}
|
||
|
fd_added = 1;
|
||
|
}
|
||
|
if (!fd_added) {
|
||
|
goto end;
|
||
|
}
|
||
|
/*
|
||
|
* Poll but don't block so we can quickly identify the faulty events and
|
||
|
* clean them afterwards from the wait queue.
|
||
|
*/
|
||
|
ret = lttng_poll_wait(&events, 0);
|
||
|
if (ret < 0) {
|
||
|
goto error;
|
||
|
}
|
||
|
nb_fd = ret;
|
||
|
for (i = 0; i < nb_fd; i++) {
|
||
|
/* Get faulty FD. */
|
||
|
uint32_t revents = LTTNG_POLL_GETEV(&events, i);
|
||
|
int pollfd = LTTNG_POLL_GETFD(&events, i);
|
||
|
cds_list_for_each_entry_safe(wait_node, tmp_wait_node,
|
||
|
wait_queue, head) {
|
||
|
if (pollfd == wait_node->app->sock &&
|
||
|
(revents & (LPOLLHUP | LPOLLERR))) {
|
||
|
cds_list_del(&wait_node->head);
|
||
|
ust_app_destroy(wait_node->app);
|
||
|
free(wait_node);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (nb_fd > 0) {
|
||
|
DBG("Wait queue sanitized, %d node were cleaned up", nb_fd);
|
||
|
}
|
||
|
end:
|
||
|
lttng_poll_clean(&events);
|
||
|
return;
|
||
|
error:
|
||
|
lttng_poll_clean(&events);
|
||
|
error_create:
|
||
|
ERR("Unable to sanitize wait queue");
|
||
|
return;
|
||
|
}
|
||
|
/*
|
||
|
* Dispatch request from the registration threads to the application
|
||
|
* communication thread.
|
||
|
*/
|
||
| ... | ... | |
|
int ret;
|
||
|
struct cds_wfq_node *node;
|
||
|
struct ust_command *ust_cmd = NULL;
|
||
|
struct {
|
||
|
struct ust_app *app;
|
||
|
struct cds_list_head head;
|
||
|
} *wait_node = NULL, *tmp_wait_node;
|
||
|
struct ust_reg_wait_node *wait_node = NULL, *tmp_wait_node;
|
||
|
CDS_LIST_HEAD(wait_queue);
|
||
| ... | ... | |
|
/* Atomically prepare the queue futex */
|
||
|
futex_nto1_prepare(&ust_cmd_queue.futex);
|
||
|
/*
|
||
|
* Make sure we don't have node(s) that have hung up before receiving
|
||
|
* the notify socket. This is to clean the list in order to avoid
|
||
|
* memory leaks from notify socket that are never seen.
|
||
|
*/
|
||
|
sanitize_wait_queue(&wait_queue);
|
||
|
do {
|
||
|
struct ust_app *app = NULL;
|
||
|
ust_cmd = NULL;
|
||
| src/bin/lttng-sessiond/ust-app.c | ||
|---|---|---|
|
call_rcu(&obj->head, close_notify_sock_rcu);
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
* Destroy a ust app data structure and free its memory.
|
||
|
*/
|
||
|
void ust_app_destroy(struct ust_app *app)
|
||
|
{
|
||
|
if (!app) {
|
||
|
return;
|
||
|
}
|
||
|
call_rcu(&app->pid_n.head, delete_ust_app_rcu);
|
||
|
}
|
||
| src/bin/lttng-sessiond/ust-app.h | ||
|---|---|---|
|
void ust_app_notify_sock_unregister(int sock);
|
||
|
ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
|
||
|
struct consumer_socket *socket, int send_zero_data);
|
||
|
void ust_app_destroy(struct ust_app *app);
|
||
|
#else /* HAVE_LIBLTTNG_UST_CTL */
|
||
| ... | ... | |
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
static inline
|
||
|
void ust_app_destroy(struct ust_app *app)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
#endif /* HAVE_LIBLTTNG_UST_CTL */
|
||