Le principe : le programme principal initialise une sémaphore (sem_init), puis fixe timeout en prenant l'heure actuelle (gettimeofday), et en y ajoutant un nombre de secondes pour indiquer jusqu'à quelle heure pourra s'exécuter la fonction. Il lance ensuite un thread (pthread_create) qui contient une fonction s'exécutant en 5 secondes. Cette dernière incrémente une sémaphore à la fin de son traitement (sem_post). Le programme principal, après le lancement du thread, attendra l'incrémentation de la sémaphore (sem_timedwait). Si le thread dépasse le temps d'attente, la fonction sem_timedwait renverra -1, et errno sera fixé à ETIMEDOUT. On peut ainsi effectuer un traitement différent de l'exécution normale, comme par exemple enregistrer dans un log qu'une fonction a dépassé le temps d'exécution qui lui était accordé.

Voici le code :

#include <pthread.h>
#include <sys/time.h>
#include <semaphore.h>
#include <errno.h>
#include <iostream>
using namespace std;
const unsigned int TIMEOUT = 3;

sem_t my_sem;

void *ThreadProcess(void *arg) {
   for(unsigned int i = 0 ; i < 5 ; i ++ ) {
      cout << i << endl;
      sleep(1);
   }
   sem_post(&my_sem);
}

int main (int argc, char *argv[]) {
   pthread_t thread;
   struct timespec my_timeout;
   struct timeval now;
   gettimeofday(&now,NULL);
   my_timeout.tv_sec = now.tv_sec + TIMEOUT;
   my_timeout.tv_nsec = now.tv_usec * 1000;
   pthread_create(&thread, NULL,ThreadProcess,NULL );
   int ret = sem_timedwait(&my_sem,&my_timeout);
   if ((ret==-1)&&(errno==ETIMEDOUT)) {
      cout << "Timeout !" << endl;
      pthread_cancel(thread);
   }
  else {
      pthread_join(thread,NULL);
  }
  return 0;
}

Pour que l'exécution se passe normalement, il suffit de fixer TIMEOUT en dessous de 5, pour déclencher le timeout, il faut le placer au dessus de 5. La compilation du programme s'effectue ainsi (en imaginant que le code soit placé dans un fichier nommé sem.cpp) :

g++ -o sem sem.cpp -pthread

Vous pouvez ainsi adapter et intégrer cet exemple dans vos projet ou cette sécurité est nécessaire. Ce code est facilement transposable en C.

Bon dev' !


Fabien (eponyme)