Я создал таймер POSIX в основной функции моей программы. Каждый поток основной программы устанавливает таймер так, что по истечении этого срока обработчик сигнала обновляет одну переменную, которая пробуждает следующий поток того же процесса.POSIX таймер зависает после нескольких прогонов
Таймер работает нормально большую часть времени, но не всегда. Он иногда завершает полное выполнение, в то время как в других запусках он зависает. Каковы могут быть возможные причины? Мое подозрение связано с доставкой сигнала.
Вот код:
#define _GNU_SOURCE
#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 <signal.h>
#include <errno.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syscall.h>
#define NUM_THREADS 10
#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1
int ret;
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
long long freq_nanosecs;
sigset_t mask;
struct sigaction sa;
sem_t sem[NUM_THREADS];
sem_t mute;
pthread_t tid[NUM_THREADS];
int state = 0;
static void handler(int sig, siginfo_t *si, void *uc)
{
ret = sem_post(&sem[(state+1)%NUM_THREADS]);
if (ret)
{
printf("Error in Sem Post\n");
}
state++;
}
void *threadA(void *data_)
{
int i = 0, s,n,value;
long int loopNum;
int turn = (intptr_t)data_;
struct timespec tval_result,tval_result2;
int sid = syscall(SYS_gettid);
FILE *fp;
fp=fopen("ipc.out","a");
fprintf(fp,"thread_%d %d\n",turn,sid);
fclose(fp);
int counter=0;
while(1)
{
ret = sem_wait(&sem[turn]);
if (ret)
{
printf("Error in Sem Post\n");
}
//printf("Thread # -> %d\n",turn);
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 14000;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
ret = timer_settime(timerid, 0, &its, NULL);
if (ret < 0)
perror("timer_settime");
// Some heavy work
counter++;
if(counter==100)
break;
}
printf("finished %d\n",turn);
}
int main(int argc, char *argv[])
{
int data = 0;
int err,i;
sa.sa_flags = SA_RESTART;
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;
ret = timer_create(CLOCKID, &sev, &timerid);
if (ret < 0)
perror("timer_create");
sem_init(&sem[0], 0, 1);
for (i = 1; i < NUM_THREADS; ++i)
{
sem_init(&sem[i], 0, 0);
}
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));
data++;
}
pthread_exit(NULL);
}
В соответствии с этим, эта программа должна печатать
finished 0
finished 1
finished 2
finished 3
finished 4
finished 5
finished 6
finished 7
finished 8
finished 9
Часть времени он печатает как это, но большую часть времени, программа виснет.
Спасибо !. Это имеет смысл, что вы объяснили. Я должен изменить программу, чтобы избежать любого состояния гонки. Хотя изменения, которые вы мне сказали выше, не решают эту проблему, но это стоит того. – Scissor
Спасибо @kaylum за ваше объяснение. Он решил мою проблему. – Scissor