Project

General

Profile

Bug #539 » bug539.diff

David Goulet, 06/06/2013 03:50 PM

View differences:

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 */
(2-2/5)