Таймер зависает через некоторое время
Я запускаю следующую программу, которая реализует таймер. Когда поток просыпается после получения сигнала по условной переменной от предыдущего запущенного потока, он создает таймер и отправляет сигнал следующему потоку по истечении таймера. Я хочу, чтобы он работал в течение некоторого времени, но таймер перестает тикать после некоторых запусков.
//Import
#define _POSIX_C_SOURCE 199309
#include <sched.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#define NUM_THREADS 10
#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1
timer_t timerid;
pthread_cond_t condA[NUM_THREADS+1] = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t tid[NUM_THREADS];
int state = 0;
static void handler(int sig, siginfo_t *si, void *uc)
{
if(si->si_value.sival_ptr != &timerid){
printf("Stray signal\n");
} else {
//printf("Caught signal %d from timer\n", sig);
}
pthread_cond_signal(&condA[state]);
}
void *threadA(void *data_)
{
int i = 0, s;
long int loopNum, j;
int turn = (intptr_t)data_;
struct timeval tval_result;
// Timer's part starts
struct sigevent sev;
struct itimerspec its;
long long freq_nanosecs;
sigset_t mask;
struct sigaction sa;
// TImer'spart ends
while(1)
{
/* Wait for state A */
pthread_mutex_lock(&mutex);
for (;state != turn;)
{
s = pthread_cond_wait(&condA[turn], &mutex);
if (s != 0)
perror("pthread_cond_wait");
// printf("main(): state = %d\n", state);
}
pthread_mutex_unlock(&mutex);
//do stuff
for(j=0;j<10000;j++)
{//some dummy time consuming works}
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sigaction(SIG, &sa, NULL);
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
timer_create(CLOCKID, &sev, &timerid);
/* Start the timer */
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 2000;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
timer_settime(timerid, 0, &its, NULL);
pthread_mutex_lock(&mutex);
state = (state +1)%NUM_THREADS;
//pthread_cond_signal(&condA[state]);
pthread_mutex_unlock(&mutex);
// Timer's code ends
}
}
int main(int argc, char *argv[])
{
int data = 0;
int err;
while(data < NUM_THREADS)
{
//create our threads
err = pthread_create(&tid[data], NULL, threadA, (void *)(intptr_t)data);
if(err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
// printf("\n Thread created successfully\n");
data++;
}
pthread_exit(NULL);
}
Хотя никаких операторов printf не выполняется, почему оно замораживается через некоторое время? Если нет. таймеры ограничены, какую другую стратегию я должен использовать, чтобы исправить эту проблему?
1 ответ
POSIX говорит:
Не безопасно использовать функцию pthread_cond_signal() в обработчике сигналов, который вызывается асинхронно.
Скорее всего, вы портите состояние pthread_cond_wait
/pthread_cond_signal
и все может случиться.
Не смешивайте потоки и обработчики сигналов, это приводит только к безумию. В обработчике сигналов разрешено делать очень мало вещей, еще меньше связанных с потоками, очень трудно гарантировать, что правильный поток завершит обработку правильного сигнала и т. Д.
Если вы в любом случае выполняете потоки, внедряете таймер в одном потоке, который вычисляет, сколько времени ему нужно, чтобы перевести следующее событие в неактивный режим (не просто жестко запрограммируйте его на период таймера, так как это приведет к смещению вашего таймера), так много спите и позвонить pthread_cond_signal
,
Кроме того, плохо иметь голую pthread_cond_signal
звонки и чаще всего ошибка. Вам может не повезти, и вы можете вызвать его прямо перед тем, как другой поток выполнит pthread_cond_wait
и ваш сигнал потеряется. Обычная вещь, которую нужно сделать - это установить переменную (защищенную мьютексом, поэтому pthread_cond_signal
хочет мьютекс), а затем сигнализировать, что переменная установлена.
Если вы думаете, что это слишком много работы, переменные условия, вероятно, не являются правильным механизмом в этом случае, и вы должны использовать вместо этого семафоры. между прочим sem_post
законно вызывать из обработчика сигнала в соответствии с POSIX, но я все еще считаю плохой идеей смешивать потоки с сигналами.