Project

General

Profile

Bug #324 » pthread_cond_patch.diff

David Goulet, 09/18/2012 04:52 PM

View differences:

src/bin/lttng-sessiond/consumer.h
#ifndef _CONSUMER_H
#define _CONSUMER_H
#include <semaphore.h>
#include <common/consumer.h>
#include <common/hashtable/hashtable.h>
#include <lttng/lttng.h>
......
enum lttng_consumer_type type;
pthread_t thread; /* Worker thread interacting with the consumer */
sem_t sem;
/* Conditions used by the consumer thread to indicate readiness. */
pthread_cond_t cond;
pthread_condattr_t condattr;
pthread_mutex_t cond_mutex;
/* Mutex to control consumerd pid assignation */
pthread_mutex_t pid_mutex;
src/bin/lttng-sessiond/main.c
#include <grp.h>
#include <limits.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
......
.cmd_sock = -1,
.pid_mutex = PTHREAD_MUTEX_INITIALIZER,
.lock = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
.cond_mutex = PTHREAD_MUTEX_INITIALIZER,
};
static struct consumer_data ustconsumer64_data = {
.type = LTTNG_CONSUMER64_UST,
......
.cmd_sock = -1,
.pid_mutex = PTHREAD_MUTEX_INITIALIZER,
.lock = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
.cond_mutex = PTHREAD_MUTEX_INITIALIZER,
};
static struct consumer_data ustconsumer32_data = {
.type = LTTNG_CONSUMER32_UST,
......
.cmd_sock = -1,
.pid_mutex = PTHREAD_MUTEX_INITIALIZER,
.lock = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
.cond_mutex = PTHREAD_MUTEX_INITIALIZER,
};
/* Shared between threads */
......
consumer_data->cmd_sock =
lttcomm_connect_unix_sock(consumer_data->cmd_unix_sock_path);
if (consumer_data->cmd_sock < 0) {
sem_post(&consumer_data->sem);
pthread_cond_signal(&consumer_data->cond);
PERROR("consumer connect");
goto error;
}
/* Signal condition to tell that the kconsumerd is ready */
sem_post(&consumer_data->sem);
pthread_cond_signal(&consumer_data->cond);
DBG("consumer command socket ready");
} else {
ERR("consumer error when waiting for SOCK_READY : %s",
......
int ret;
struct timespec timeout;
timeout.tv_sec = DEFAULT_SEM_WAIT_TIMEOUT;
timeout.tv_nsec = 0;
/* Setup pthread condition */
ret = pthread_condattr_init(&consumer_data->condattr);
if (ret != 0) {
errno = ret;
PERROR("pthread_condattr_init consumer data");
goto error;
}
/* Setup semaphore */
ret = sem_init(&consumer_data->sem, 0, 0);
if (ret < 0) {
PERROR("sem_init consumer semaphore");
/*
* Set the monotonic clock in order to make sure we DO NOT jump in time
* between the clock_gettime() call and the timedwait call. See bug #324
* for a more details and how we noticed it.
*/
ret = pthread_condattr_setclock(&consumer_data->condattr, CLOCK_MONOTONIC);
if (ret != 0) {
errno = ret;
PERROR("pthread_condattr_setclock consumer data");
goto error;
}
ret = pthread_cond_init(&consumer_data->cond, &consumer_data->condattr);
if (ret != 0) {
errno = ret;
PERROR("pthread_cond_init consumer data");
goto error;
}
......
goto error;
}
/* We are about to wait on a pthread condition */
pthread_mutex_lock(&consumer_data->cond_mutex);
/* Get time for sem_timedwait absolute timeout */
ret = clock_gettime(CLOCK_REALTIME, &timeout);
ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
if (ret < 0) {
PERROR("clock_gettime spawn consumer");
/* Infinite wait for the kconsumerd thread to be ready */
ret = sem_wait(&consumer_data->sem);
ret = pthread_cond_wait(&consumer_data->cond,
&consumer_data->cond_mutex);
} else {
/* Normal timeout if the gettime was successful */
timeout.tv_sec += DEFAULT_SEM_WAIT_TIMEOUT;
ret = sem_timedwait(&consumer_data->sem, &timeout);
ret = pthread_cond_timedwait(&consumer_data->cond,
&consumer_data->cond_mutex, &timeout);
}
if (ret < 0) {
if (errno == ETIMEDOUT) {
pthread_mutex_unlock(&consumer_data->cond_mutex);
if (ret != 0) {
errno = ret;
if (ret == ETIMEDOUT) {
/*
* Call has timed out so we kill the kconsumerd_thread and return
* an error.
*/
ERR("The consumer thread was never ready. Killing it");
ERR("Condition timed out. The consumer thread was never ready."
" Killing it");
ret = pthread_cancel(consumer_data->thread);
if (ret < 0) {
PERROR("pthread_cancel consumer thread");
}
} else {
PERROR("semaphore wait failed consumer thread");
PERROR("pthread_cond_wait failed consumer thread");
}
goto error;
}
(5-5/5)