c: Signal et threads ...
Répondre à la discussion
Affichage des résultats 1 à 15 sur 15

c: Signal et threads ...



  1. #1
    destroyedlolo

    c: Signal et threads ...


    ------

    Salut,

    Un sujet bien présent sur le web ... mais je n'ai pas réussi a trouver de réponse
    Bref, voici mon probleme :

    Je crée un thread qui lance certaines actions de manière cyclique après une attente, genre

    Code:
    void monthread(){
       sleep( temps_d_attente );
       plein_de_choses_a_faire();
    }
    Sauf que si la configuration a changé, le sleep() doit etre interrompu pour lancer les actions.

    La doc de sleep() indique qu'il attend la période spécifié OU l'arrivé d'un signal ... donc j'ai pensé à

    Code:
    void *slave(){
    	for(;;){
    		sleep(30);
    		mes_trucs_a_faire();
    	}
    
    	return NULL;	/* Avoid warning */
    }
    
    int main(){
    	pthread_t thrd;
    
    		/* Create a detached thread */
    	pthread_attr_t thread_attr;
    	assert(!pthread_attr_init (&thread_attr));
    	assert(!pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED));
    	if(pthread_create( &thrd, &thread_attr, slave, NULL )){
    		perror("Slave creation");
    		exit(EXIT_FAILURE);
    	}
    
    	puts("wait 15s");
    	sleep(15);
    	pthread_kill( thrd, SIGUSR1 );
    	pause();
    
    	return(EXIT_SUCCESS);
    }
    Sauf que la, ca ce termine par un
    $ ./TestSignal
    wait 15s
    Tue Aug 21 15:20:04 2018

    User defined signal 1
    J'ai trouvé sur le web qu'il faut mettre un signal handler, ... ok, mon code devient
    Code:
    void donothing_handler(){
    /* Does strictly nothing ... but avoid the process to be interrupted by
     * the standard handler
     */
    }
    
    void *slave(){
    	for(;;){
    		sleep(30);
    		mes_trucs_a_faire();
    	}
    
    	return NULL;	/* Avoid warning */
    }
    
    int main(){
    	pthread_t thrd;
    
    	signal(SIGSEGV,donothing_handler);
    
    		/* Create a detached thread */
    	pthread_attr_t thread_attr;
    	assert(!pthread_attr_init (&thread_attr));
    	assert(!pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED));
    	if(pthread_create( &thrd, &thread_attr, slave, NULL )){
    		perror("Slave creation");
    		exit(EXIT_FAILURE);
    	}
    
    	puts("wait 15s");
    	sleep(15);
    	pthread_kill( thrd, SIGUSR1 );
    	pause();
    
    	return(EXIT_SUCCESS);
    }
    mais ca ne marche pas mieux

    Bref, ou est mon erreur.

    Sinon, je pourrai passé par les timerfd() et autre eventfd() mais je trouve que vu que je n'attend que 2 chose sur un thread, c'est un peu sortir le marteau pilon pour pas grand chose.

    Merci pour vos éclairages

    -----

  2. #2
    pm42

    Re : c: Signal et threads ...

    Il ne faut pas utiliser sleep ni les signaux pour cela dans les threads. Ce n'est pas adapté ni performant. Déjà, un signal est fait pour être envoyé à un processus, pas un thread et date d'avant le multithreading.

    Dans ton cas, il faut utiliser ceci : http://pubs.opengroup.org/onlinepubs...timedwait.html

  3. #3
    destroyedlolo

    Re : c: Signal et threads ...

    Merci Pm42 pour cette suggestion ... mais mes recherches m’amène une autre question :
    dans (tous ?) les exemples que j'ai trouvé, les pthread_cond_signal() et pthread_cond_wait() sont entourés de pthread_mutex_lock() puis son pendant pthread_mutex_unlock().

    C'est due à l’implémentation des conditions ou puis-je m'en passer sachant qu'il n'y a aucune information partagée entre le main() et les thread() ? Toutes les infos sont strictement locales aux threads.

    Merci

  4. #4
    pm42

    Re : c: Signal et threads ...

    C'est à vérifier mais je suis presque sur que le mutex est indispensable. Cela fait longtemps que je n'ai plus fait de multithreading "à la main" comme ça.

  5. A voir en vidéo sur Futura
  6. #5
    Jack
    Modérateur

    Re : c: Signal et threads ...

    C'est écrit dans la doc il me semble: la variable "condition" doit toujours être protégée par un mutex.

  7. #6
    destroyedlolo

    Re : c: Signal et threads ...

    En effet, la doc dit
    "Une variable condition doit toujours être associée à un mutex, pour éviter les accès concurrents où un thread se prépare à attendre une condition et un autre signale la condition juste avant que le premier n'attende réellement."
    Et j'ai lu ailleurs que pthread_cond_wait() levait le lock lors de l'attente ... mouai, j'ai du mal a voir pourquoi il ne le font pas toute cette sauce en interne et que si la condition est déjà signalée, on passe ; mais bon, soit ...
    Je referai un code demain avec cette solution.

    Par contre pm42, quand tu dis
    Cela fait longtemps que je n'ai plus fait de multithreading "à la main" comme ça
    tu utilises quoi ? Les classes de la std ?

    Parce que mon programme est un C++ : je n'ai pas utilisé les threads de la STD, déjà parce que je ne les connais pas (mais bon, ca s'apprend), mais surtout parce que je n'ai pas trouvé de moyen de les conserver. Ce que je veux dire, c'est du "launch & forget", ils ne sont créer que lorsque certains éventements arrivent, font leurs trucs et meurent d'eux même une fois fini, pas besoin de garder le moindre lien vers eux.
    Je me suis dit que si l'objet thread n'était qu'une variable locale, il disparaitra à la fin de la fonction ... et le thread avec. Le stocker dans une collection quelconque ne servait strictement a rien et allait devenir pénible a gérer.
    Les alloués par new serait peut etre la solution ... mais qu'adviendra-t-il du conteneur une fois le thread mort ?

    Bref, ca m'a paru plus simple d'utiliser la méthode C où au moins je maitrise se qu'il se passe.
    Dernière modification par destroyedlolo ; 23/08/2018 à 01h49.

  8. #7
    pm42

    Re : c: Signal et threads ...

    Citation Envoyé par destroyedlolo Voir le message
    tu utilises quoi ? Les classes de la std ?
    En général, j'évite le C++ mais ce que je voulais dire, c'est que j'utilise plutôt soit des frameworks orientés traitement parallèle (ExecutorService en Java, Akka pour le mode acteur, Spark, etc).
    Ou des outils plus simples comme les variables atomiques plutôt que les mutex/condition...

    Mais dans ton cas, ton choix est le bon.

    Citation Envoyé par destroyedlolo Voir le message
    Parce que mon programme est un C++ : je n'ai pas utilisé les threads de la STD, déjà parce que je ne les connais pas (mais bon, ca s'apprend), mais surtout parce que je n'ai pas trouvé de moyen de les conserver..
    Ton analyse est pertinente. La solution est d'apppeler detach() sur le thread avant d'arriver sur le destructeur.
    https://stackoverflow.com/questions/...tdthreaddetach

    Note toutefois que quand ton programme se termine, tes threads seront interrompus brutalement et qu'aucun code de fin/nettoyage ne sera appelé si tu as fait detach().
    Mais si tu lis l'anglais, tout est bien expliqué dans le lien stackoverflow que j'ai mis.

  9. #8
    invite6486d7bd

    Re : c: Signal et threads ...

    Je ne vois pas pourquoi vous tenez à employer des threads (même si on est d'accord qu'il peut évidemment y avoir de bonnes raisons à les employer).

    Une méthode plus directe et standard consiste à tester l'existence de messages dans Main (ou ailleurs), de les récupérer et de traiter le cas correspondant au message.
    En gros, on produit une boucle sans fin dans le Main, qui teste à chaque tour l'existence ou pas d'un message par PeekMessage, qui renseigne msg par pointeur.
    Selon la valeur de msg qui est du type MSG, on traite le cas. (On peut aussi bloquer l'attente d'un message par GetMessage, au choix)
    Un des message à prendre en compte impérativement étant bien entendu celui qui initie la fermeture de l'application, le message ayant le valeur WM_QUIT.

    Dans votre cas de figure, au lieu de mettre en attente un thread pendant 15 secondes (par exemple), il vaut mieux à mon avis lancer un SetTimer avec un tempo de 15*1000 millisecondes, en précisant un ID de votre choix qui permettra d'identifier le message correspondant à ce tempo de 15 secondes et qui sera du type WM_TIMER.

    Donc lorsque vous constatez un message du type WM_TIMER, vous vérifiez qu'il possède bien l'ID de votre choix et donc vous lancez le traitement "des choses à faire", et ce donc toutes les 15 secondes, ou pas, puisque c'est vous qui décidez du code à lancer lorsque vous traitez le message.

    Voir par exemple ici : https://adilevin.wordpress.com/tag/wm_timer/
    Sinon, il y a plein de sites qui donnent des exemples tout faits.

  10. #9
    destroyedlolo

    Re : c: Signal et threads ...

    Salut,

    Ben déjà, mon projet est sous Linux comme tout le reste de mon info.

    Etre multithreadé est a la fois plus pratique dans le design et plus efficace qu'une boucle comme tu le décris :
    - d'un parce que certains événements viennent d'MQTT dont la librairie génère elle meme des threads lorsque des messages sont recus
    - certaines taches peuvent etre relativement longues (quelques secondes (*) ) ... Donc niveau conception et design, c'est plus simple : on n'a pas a s'occuper de ce qu'il se passe à coté, on ne bloque rien. Les différentes taches vivent leur vies et se terminent lorsqu'elles n'ont plus rien a faire, un peu dans le genre des micro service mais en interne a l'applie.

    C'est en gros ce qui est fait dans des grosses plateformes d'intégration telles que webMethods. C'est extrêmement efficace.

    (*) mon projet est un ordonnanceur pour ma domotique : on ne peut pas se permettre d'avoir des temps de réaction de plusieurs secondes.

    A+

  11. #10
    destroyedlolo

    Re : c: Signal et threads ...

    Bonjour,

    Juste un ch'tit message pour vous remercier car ca fonctionne très bien.

    Est-ce que ca aurait un intérêt que je publie mon code de test ?

    A+

  12. #11
    pm42

    Re : c: Signal et threads ...

    Citation Envoyé par destroyedlolo Voir le message
    Est-ce que ca aurait un intérêt que je publie mon code de test ?
    Pas pour moi parce que je ne fais plus de C++ mais je suis content pour toi que ça marche.

  13. #12
    polo974

    Re : c: Signal et threads ...

    Citation Envoyé par destroyedlolo Voir le message
    Bonjour,

    Juste un ch'tit message pour vous remercier car ca fonctionne très bien.

    Est-ce que ca aurait un intérêt que je publie mon code de test ?

    A+
    Bonjour,
    je suis intéressé par ton bout de code, car moi, quand j'ai un cas similaire (un thread en attente d'un "truc", j'utilise un bon vieux select avec un timeout (ben voui, vieille école...) et selon le cas et l'humeur, un pipe (unidirectionnel) ou un socketpair (bidir).

    sinon, j'ai essayé le eventfd(), et j'en suis revenu après plantages aléatoires (perte de l'event, thread pas réveillé, programme bloqué, ça fait mal en prod...), après recherche sur le web, il semble qu'il y a (eu ?) un bug sur cette fonctionnalité, mais comme c'est facile à remplacer par un pipe, je n'ai pas creusé plus loin...
    Jusqu'ici tout va bien...

  14. #13
    sandrecarpe

    Re : c: Signal et threads ...

    Salut,
    Voilà un bout de code que j'utilisais en C++11 pour faire ce que tu veux faire.

    Log.h
    Code:
    #include <thread>
    #include <mutex>
    #include <condition_variable>
    #include <iostream>
    #include <chrono>
    
    class Log
    {
    	public:
    		Log(int delay);
    		~Log();
    		void threadLog(int delay);
    		void wakeUp();
    
    	private:
    		std::condition_variable _cv;
    		std::mutex _mutex;
    		std::thread *_thread;
    
    };

    Log.cpp
    Code:
    #include "Log.h"
    
    Log::Log(int delaySec) : _cv(), _mutex(), _thread(0)
    {
    	_thread = new std::thread(&Log::threadLog, this, delaySec);
    	
    }
    
    Log::~Log()
    {
    	_thread->join();	
    }
    
    void Log::threadLog(int timeoutSec)
    {
    	std::unique_lock<std::mutex> lck(_mutex);
    
    	std::cout << "en attente...." << std::endl;
    	_cv.wait_for(lck, std::chrono::seconds(timeoutSec));
    	std::cout << "fin attente" << std::endl;
    }
    
    
    void Log::wakeUp()
    {
    	_cv.notify_all();
    }

    La ligne :
    Code:
    _cv.wait_for(lck, std::chrono::seconds(timeoutSec));
    bloque l'exécution du thread pendant timeoutSec secondes, ou attend que la méthode Log::wakeUp() soit appelée de l'extérieure

    Court et efficace

  15. #14
    polo974

    Re : c: Signal et threads ...

    Merci beaucoup
    Jusqu'ici tout va bien...

  16. #15
    destroyedlolo

    Re : c: Signal et threads ...

    Sinon, tu peux aussi regarder dans le code de mon framework Séléné qui contient des timerfd, des eventfd et d'autres trucs ...

Discussions similaires

  1. Threads - processus
    Par Linuxman99 dans le forum Programmation et langages, Algorithmique
    Réponses: 38
    Dernier message: 28/02/2017, 03h40
  2. Inter-Threads
    Par invite1e354676 dans le forum Programmation et langages, Algorithmique
    Réponses: 5
    Dernier message: 12/02/2017, 15h17
  3. Les threads en java
    Par invite585703c8 dans le forum Programmation et langages, Algorithmique
    Réponses: 0
    Dernier message: 19/06/2011, 11h14
  4. les threads sur Python
    Par invite75a667e5 dans le forum Logiciel - Software - Open Source
    Réponses: 4
    Dernier message: 16/01/2010, 22h05
  5. les threads
    Par inviteacb3e291 dans le forum Logiciel - Software - Open Source
    Réponses: 2
    Dernier message: 10/10/2005, 17h32