IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Sigaction ou signal - sans stopper le programme ?


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Informatique
    Inscrit en
    Mars 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informatique

    Informations forums :
    Inscription : Mars 2013
    Messages : 26
    Points : 26
    Points
    26
    Par défaut Sigaction ou signal - sans stopper le programme ?
    Bonjour a tous ,

    Mon problème est le suivant , dans mon programme j’exécute au début de mon main()

    Je crée un sigaction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct sigaction sig;
    sig.sa_handler = mafonction;
    sig.sa_flags = 0 ;
    sigaction(SIGALRM,&sig,NULL);
    Ensuite je lance mon alarme :
    puis je rentre dans une boucle while infinie ou je fait 2 test ,
    sur ma variable, si var == 0 je print un message X si non je print un message Y

    et ma fonction handler se charge de modifier la valeur de cette variable , le problème est lorsque je rentre dans mon handler et modifie ma variable , plus rien ne se passe
    a croire que mon programme est en pause

    Y a -t-il une solution a mon problème ?

    P.S :j'ai print un message pour vérifier si je rentrais bien dans le handler , et oui , je rentre bien

    En vous remerciant

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 377
    Points : 23 663
    Points
    23 663
    Par défaut
    Bonjour,

    Peut-on voir ton code en entier ? À ce stade, cela peut être n'importe quoi.

    Vérifie par exemple la façon dont est écrite ta condition « if … else » pour voir si ta variable ne se trouverait pas dans une condition qui ne soit prise en charge par aucune de tes deux clauses. Vérifie également si tu n'as pas une boucle infinie au sein de ton handler.

    D'autre part, ta variable est-elle une variable globale ? En principe, il faut s'efforcer de ne pas y avoir recours mais dans le cas qui nous occupe, il se peut que tu aies déclaré deux variables locales portant le même nom mais néanmoins indépendantes entre elles.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Informatique
    Inscrit en
    Mars 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informatique

    Informations forums :
    Inscription : Mars 2013
    Messages : 26
    Points : 26
    Points
    26
    Par défaut
    Voila en gros , ce qu'il y a , j'ai enlever les bout de code inutiles
    les includes également.

    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
    34
     
    int ecouteAlarm(int);
     
    int ok = 0;
     
    int main(int argc , char **argv){
     
     
    	struct sigaction sig;
    	struct sigaction sig;
    	sig.sa_handler = ecouteAlarm;
    	sig.sa_flags = 0 ;
    	sigaction(SIGALRM,&sig,NULL);
     
    	alarm(5);
    	printf("Alarm lancer \n");
     
    	while(1){
    		if(ok == 1){
    			printf("La variable vaut : %d\n",ok);
    		}else{
    			printf("La variable vaut : %d \n" , ok);	
    		}
     
    	}
     
     
    	return 0;
    }
     
    int ecouteAlarm(int arg){
    	printf("Alarm terminé \n");
    	ok = 1 ;
    }

    Je te remercie de me consacrer un peut de temps ^^

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 377
    Points : 23 663
    Points
    23 663
    Par défaut
    Deux petites choses :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	struct sigaction sig;
    	struct sigaction sig;
    … tu définis deux fois la même variable ;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	if(ok == 1){
    			printf("La variable vaut : %d\n",ok);
    		}else{
    			printf("La variable vaut : %d \n" , ok);	
    		}
    … tes deux clauses font rigoureusement la même chose (à un espace près). Tu ne peux donc pas les distinguer à l'œil nu.

    Pour le reste, ça fonctionne chez moi : « ok » passe de zéro à un et les printf() en font état. Qu'obtiens-tu chez toi ? Es-tu sûr que ce que tu prends pour une « pause » n'est pas en fait la même ligne qui se répète ad vitam æternam ?

    D'autre part, il faut penser à bien inclure les bons fichiers d'entête « *.h », il y aurait éventuellement une macro à définir (telle que _POSIX_SOURCE) et tu devrais utiliser l'appel pause() plutôt que faire une boucle infinie.

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Informatique
    Inscrit en
    Mars 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informatique

    Informations forums :
    Inscription : Mars 2013
    Messages : 26
    Points : 26
    Points
    26
    Par défaut
    Ce que je t'ais envoyer , fonctionne chez moi aussi ,
    mais une fois que je remet ce bout de code dans son contexte , rien ne vas plus

    Au faite , je code un programme serveur-client

    et mon serveur qui lui ne s’arrête jamais , est dans une boucle while et attend que des clients
    viennent se connectés , lorsque qu'un client se connecte j'effectue une fonction et je lance larme (5sec) , une fois l’alarme lancer , apres les 5 sec je rentre dans mon handler j'effectue le traitement et après ça je ne suis plus dans mon while , mon serveur est comme mis en pause , et quand un client essai de se connecté le serveur ne le détecte plus.


    il est possible de vérifier si une alarme est lancé grâce a la fonction select() ?

    Merci

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 377
    Points : 23 663
    Points
    23 663
    Par défaut
    Citation Envoyé par SoulGoodMan Voir le message
    est dans une boucle while et attend que des clients viennent se connectés , lorsque qu'un client se connecte j'effectue une fonction et je lance larme (5sec) , une fois l’alarme lancer , apres les 5 sec je rentre dans mon handler j'effectue le traitement et après ça je ne suis plus dans mon while , mon serveur est comme mis en pause , et quand un client essai de se connecté le serveur ne le détecte plus.

    il est possible de vérifier si une alarme est lancé grâce a la fonction select() ?
    La réception d'un signal débloque tout appel bloquant après avoir quitté le handler. Si ton appel à select() n'a pas prévu ce cas, il se peut que tu entres dans une boucle infinie. Il faudrait que l'on voie ton code pour le dire.

    Par ailleurs, tu ne peux pas programmer plusieurs « alarm() » simultanées. Chaque fois que tu appelles cette primitive, tu réinitialises le compteur à la nouvelle valeur que tu lui passes. Si c'est bien ce que tu veux faire, peut-être vaut-il mieux se tourner vers le champ timeout de l'appel select().

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Informatique
    Inscrit en
    Mars 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informatique

    Informations forums :
    Inscription : Mars 2013
    Messages : 26
    Points : 26
    Points
    26
    Par défaut
    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
    34
    35
    36
    37
    38
    39
    40
     
           	struct sigaction sig;
    	sig.sa_handler = actionAlarme;
    	sig.sa_flags = 0;
    	sigaction(SIGALRM , &sig,NULL);
           //Initialisation des sockets
    	while(1){
                    //variable globale init a 0
    		if(ok == 1){
    			printf("ok vaut %d \n",ok);	
    		}else{
    			printf("jok vaut %d \n" , ok);	
    		}
     
    		FD_ZERO(&ecoute);// variable de type fd_set 
    		FD_ZERO(&inscription);// variable de type fd_set
    		tvInsc.tv_usec = 0 ;
    		tvInsc.tv_sec = 1;
    		FD_SET(serveur , &inscription);
    		select(serveur +1 ,&inscription , NULL,NULL,&tvInsc);
    		if(FD_ISSET(serveur  ,&inscription)){
    			SYS(client = accept(serveur,(SOCKADDR*)&csin,&clilen));
    			printf("Un nouveau client vient de se connecte.\n");
    			if(MAXCLIENT== nbrClient){
    				refuserJoueur(client);	
    			}else{
                                    //C'est dans cette fonction que je lance l'alarm 
                                    //une seul fois , lorsque le nombre de client est de 1
    				accepterJoueur(client);
    			}
     
    		}
    		if(nbrJClient){
    			ecouterClient();//Fonction qui ecoute si un client me parle 
    		}
    	}
    //Fin du main
    void actionAlarme(int arg){
    	ok = 1 ;
    }
    Voila ce que j'ai dans mon while + la fonction handler

    Si il vous faut des informations en plus , je l'es mettrais

    Merci

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 377
    Points : 23 663
    Points
    23 663
    Par défaut
    Citation Envoyé par SoulGoodMan Voir le message

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    		if(ok == 1){
    			printf("ok vaut %d \n",ok);	
    		}else{
    			printf("jok vaut %d \n" , ok);	
    		}
    Je réitère : ton « if…else » et ses deux lignes ne servent à rien. Laisse juste un seul printf() qui affiche directement la valeur de « ok ».


    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
    
    		select(serveur +1 ,&inscription , NULL,NULL,&tvInsc);
    
    		if(FD_ISSET(serveur  ,&inscription)){
    			SYS(client = accept(serveur,(SOCKADDR*)&csin,&clilen));
    			printf("Un nouveau client vient de se connecte.\n");
    			if(MAXCLIENT== nbrClient){
    				refuserJoueur(client);	
    			}else{
                                    //C'est dans cette fonction que je lance l'alarm 
                                    //une seul fois , lorsque le nombre de client est de 1
    				accepterJoueur(client);
    			}
    
    		}
    		if(nbrJClient){
    			ecouterClient();//Fonction qui ecoute si un client me parle 
    		}
    	}
    //Fin du main
    void actionAlarme(int arg){
    	ok = 1 ;
    }
    C'est au niveau de la ligne en rouge que ça pose problème. En l'état actuel des choses, tu fais ceci : tu attends que select() débloque puis tu testes si c'est le socket du serveur qui signale une nouvelle connexion entrante. Si ce n'est pas le cas, tu passes immédiatement au « if » suivant dans lequel tu entres si tu es réputé avoir déjà des clients en cours.

    Or, dans le cas qui te gène, c'est ni l'un ni l'autre : select() sort parce que alarm() l'a débloqué. Comme tu estimes que si ce n'est pas le serveur, c'est forcément le client qui te parles, tu vas te mettre à l'écoute de celui-ci alors qu'il n'a rien à dire et donc entrer dans un nouvel état bloquant, d'où la « pause ».

    Au passage, c'est exactement pour cela que « select() » a été mis en place : pouvoir se mettre simultanément à l'écoute de plusieurs descripteurs et ne réagir qu'à partir du moment où l'un d'eux à quelque chose à dire (ou est prêt à recevoir des données). Il faut donc ajouter le socket serveur ET celui de chacun de tes clients dans le même FD_SET, puis utiliser un seul select() pour tout faire.

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Informatique
    Inscrit en
    Mars 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informatique

    Informations forums :
    Inscription : Mars 2013
    Messages : 26
    Points : 26
    Points
    26
    Par défaut
    Dans ma fonction ecouterClient() il y a cela :

    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
     
    	int maxFD = 0; // permet de garder la valeur du plus grand descripteur
    	int i;
     
     
    	for(i = 0; i < nbClient; i++){
    		//ajout de la ieme socket dans le fdset;
    		FD_SET(r.joueurs[i].sock,&ecoute);
    		if(tableClient[i].sock >= maxFD ){
    			maxFD = tableClient[i].sock;
    		}
    	}
    	tv.tv_usec = 1000;
    	tv.tv_sec = 0;
     
    	select( maxFD + 1, &ecoute, NULL, NULL, &tv);
     
    	for(i = 0; i < nbClient; i++){
    		if(FD_ISSET(tableClient[i].sock, &ecoute)){
    			int n=recv(tableClient[i].sock,&msg,sizeof(message),0);
    			if(n == 0)
    			{
    				supprimerClient(i);
    			}
    		}
    	}
    tu croit que le problème viendrais de la ?

    Parce que j'ai mis un temps limité au select associé aux clients , donc il ne seras jamais bloquant a mon avis , mais sa ne coûte rien d'essayer

    Je te remercie pour tes reponses , je vais essayé cela demain , et je te tiens au courant

    Merci a toi

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 377
    Points : 23 663
    Points
    23 663
    Par défaut
    Citation Envoyé par SoulGoodMan Voir le message
    tu croit que le problème viendrais de la ?

    Parce que j'ai mis un temps limité au select associé aux clients ,
    Ce n'est pas le timeout qui va rendre un appel bloquant ou non. select() sert justement à se mettre en attente de plusieurs descripteurs de fichiers et/ou sockets bloquants et à sortir dès que l'un d'eux cesse de l'être.

    Il faut mettre ton socket serveur et ceux de tes clients dans un même jeu et installer un seul et unique select() dans ton programme au sein de ta boucle principale. Ensuite, tu attends que select() sorte et là, tu as trois possibilités :

    1. Si le socket serveur est marqué, tu acceptes le nouveau client entrant ;
    2. Si un ou plusieurs des sockets clients sont marqués, tu les traites également. Ils peuvent l'être en même temps que le socket serveur ;
    3. Si aucun socket en particulier n'est marqué et, plus spécialement, si select() a renvoyé une valeur nulle ou négative, alors c'est que le timeout est arrivé à expiration (si tu as spécifié un délai mais tu ne devrais plus avoir à le faire) ou qu'un signal est arrivé entre temps et a débloqué le select(). Dans ce cas, tu fais un tour de boucle et tu la laisse réappeler select() toute seule.

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Informatique
    Inscrit en
    Mars 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informatique

    Informations forums :
    Inscription : Mars 2013
    Messages : 26
    Points : 26
    Points
    26
    Par défaut
    Je te remercie de ton aide

    Comme je travaille sur un autre projet en parallèle , je ne pourrais pas tester maintenant ce que tu me propose

    Donc , je laisse ce post en non résolu , et je te communique au plus vite le résultat

    Merci a toi

  12. #12
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 377
    Points : 23 663
    Points
    23 663
    Par défaut
    Pas de problème. On sera là.
    Bon courage.

  13. #13
    Nouveau membre du Club
    Homme Profil pro
    Informatique
    Inscrit en
    Mars 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informatique

    Informations forums :
    Inscription : Mars 2013
    Messages : 26
    Points : 26
    Points
    26
    Par défaut
    Ralalala

    Problème résolue , le problème venait du faite que je ne testait pas la valeur que me renvoyait le Select ,donc je rentrais directement dans le premier IF
    et mon programme se mettait en "pause" , comme tu ma dit , il détecte quelque chose sur la Socket serveur et rentre dans le FD_ISSET, qui lui est suivit d'un accepte qui BLOQUANT
    et voila d'ou cette fameuse PAUSE

    Parfois mieux vaut prendre du recule


    Merci 1000X pour ton aide Obsidian

    Au revoir

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. MessageBox sans stopper l'exécution du programme
    Par Irken dans le forum Windows
    Réponses: 3
    Dernier message: 24/04/2008, 14h34
  2. Réponses: 2
    Dernier message: 18/07/2006, 12h20
  3. jouer un sons sans stopper l'autre
    Par darkmalak01 dans le forum Langage
    Réponses: 2
    Dernier message: 14/10/2005, 23h54
  4. Fermer la fentre sans quitter le programme?
    Par tomburn dans le forum OpenGL
    Réponses: 13
    Dernier message: 06/12/2004, 17h02
  5. [Turbo Pascal] Lire une touche au clavier sans interrompre le programme
    Par Allelouia dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 29/03/2003, 22h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo