bonjour a tous, c'est encore moi
Voici mon problème :
Je fait une fifo pour l'entrée d'un timer, qui va attendre un delay, puis l'envoyé dans un autre thread pour qu'elle soit exécuter.
Je veux que si une opération avec un delai plus cours que celle qui est traitée arrive dans la fifo elle passe en première (deadline plus cours).
Par exemple je rempli dans ma fifo une opération (A) qui a un delay de 3 secondes, le thread d'attente se met en attente pendant 3 second. Un second passe et arrive une nouvelle opération dans la fifo (B) avec un delay de 1s. La deadline de la second opération (B) arrive avant la première (A).
C'est une fifo bloquante avec un sémaphore (et mutex pour la concurrence). Lorsque je pousse une nouvelle donnée dans la fifo, j'augmente le sémaphore de 1, et j'envoi un signal sigRtMin+1 afin de le thread sort de son attente, si il est dans le sleep. Pour éviter que mon thread reçoive le signal lorsqu'il n'en a pas besoin je bloque le signal puis le débloque (et supprime les signaux potentiels en attentes).
Parfois je reçois un sigSegv (Régulièrement, voir tout le temps lorsque j'utilise Valgrind --tool=helgrind -v MonExe) via mon sémaphore qui lève une exception après avoir été interrompu pour mon signal sigRtmin+1. Je ne comprends pas comment mon sémaphore peut être interrompu par mon signal étant donnée que durant la période ou le thread est en attente sur le sémaphore le signal est censé être bloqué.
Voici le code:
voici le code du signal block/unblock
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 Code du thread Timer void Timer::run() { LOG_TRACE("Timer:: run() "); //WAKE_UP_SIGNAL = SIGRTMIN+1 Signal::signalMask(WAKE_UP_SIGNAL, Signal::E_BLOCK); while(stopRequired() == false) { _sem.acquire(); //c'est ce sémaphore qui lève l'exception while((isOperationFifoEmpty() == false)) { //récupère lélément de la fifo Signal::cleanPendingSignal(WAKE_UP_SIGNAL); Signal::signalMask(WAKE_UP_SIGNAL, Signal::E_UNBLOCK); clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &delayBeforeWakeUp, NULL); Signal::signalMask(WAKE_UP_SIGNAL, Signal::E_BLOCK); //traitement de l'operation terminé //ou traitement lié a une interruption par un signal } } Signal::cleanPendingSignal(WAKE_UP_SIGNAL); Signal::signalMask(WAKE_UP_SIGNAL, Signal::E_UNBLOCK); }
et enfin le code pour supprimer les signaux en attente
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 void Signal::signalMask(const int32_t& signal, const Signal::actionOnSignal& action) { LOG_TRACE("Signal::signalMask()"); int32_t retVal; sigset_t set; retVal = sigemptyset(&set); retVal = sigaddset(&set, signal); switch (action) { case E_BLOCK: retVal = pthread_sigmask(SIG_BLOCK, &set, NULL); break; case E_UNBLOCK: retVal = pthread_sigmask(SIG_UNBLOCK, &set, NULL); break; case E_SETMASK: retVal = pthread_sigmask(SIG_SETMASK, &set, NULL); break; default: break; } }
Je n'arrive pas a voir le problème. Concernant l'envoi du signal j'utilise l'envoie via pthread_kill(ThreadId, sigRtMin+1). Le signal possède un handler qui fait appelle a une méthode de la classe qui ne fait rien (vide), elle est juste la pour avoir un handler associé au signal.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 void Signal::cleanPendingSignal(const int32_t& signal) { LOG_TRACE("Signal::cleanPendingSignal()"); sigset_t sigpend; sigemptyset(&sigpend); sigaddset(&sigpend,signal); struct timespec ts = {0,0}; // do not wait siginfo_t siginfo; errno = 0; //j'ai essayé : while (sigtimedwait(&sigpend,&siginfo,&ts) == -1 && errno == EINTR); // et ca, j'ai le meme comportement while (sigtimedwait(&sigpend,&siginfo,&ts) == signal && errno != EAGAIN); }
Comment puis je faire pour empêcher ce signal d'interrompre le sémaphore?
J'aimerai éviter de faire un try catch...
Merci d'avance
Partager