std::cin et SIGINT

std::cin et SIGINT - C++ - Programmation

Marsh Posté le 16-12-2003 à 14:02:38    

bonjour,
 
sous linux, j'ai le soucis suivant:
j'ai un process en attente sur std::cin. Je valide chaque entrée en testant std::cin.eof(). En dehors de cela, j'ai un handler pour les signaux SIGINT, SIGHUP et SIGPIPE. Lorsque l'utilisateur envoie un C^c à l'application, celle-ci reçoit bien un signal SIGINT, mais en plus std::cin.eof() renvoie true... J'ai bien essayé de std::cin.clear(std::ios::eofbit), mais rien n'y fait. C'est gênant car je voudrait pouvoir continuer mon process en lisant sur std::cin. Je ne vois pas bien où se trouve le problème et la relation entre SIGINT et l'entrée standard.
Avez vous une idée?

Reply

Marsh Posté le 16-12-2003 à 14:02:38   

Reply

Marsh Posté le 16-12-2003 à 16:16:47    

ton code.
 
attendre std::cin.eof(), tu peux courir ...

Reply

Marsh Posté le 16-12-2003 à 16:58:03    

Taz a écrit :

ton code.


 
voici un exemple simpliste, qui a le comportement que je décris.
au prompt il ne faut bien sûr rentrer qu'une seule commande.
 
tu fais C^d => ça envoie eof, qui est détécté, et ya pas de souçis. le C^c est bien détécté, mais cin.eof renvoie true.
 

Code :
  1. /*
  2. * file   : main.cpp
  3. *
  4. */
  5. #include <iostream>
  6. #include <unistd.h>
  7. #include <sys/signal.h>
  8. static struct sigaction oldact;
  9. /*
  10. **
  11. **
  12. **
  13. */
  14. void on_signal( int signal )
  15. {
  16.         sigset_t set;
  17.         sigprocmask(SIG_BLOCK, NULL, &set );
  18.         // do the job
  19.         if( signal==SIGINT )
  20.         {
  21.                 std::cout << " ---> pid "<<getpid()<<" - interrupt set (SIGINT) <--- ";
  22.                 std::cout.flush();
  23.         }
  24. std::cout << "clearing std input status...";
  25. std::cin.clear(std::ios::eofbit);
  26. }
  27. /*
  28. **
  29. **
  30. **
  31. */
  32. void sethandler()
  33. {
  34.         struct sigaction act;
  35.         // initialisation des structures
  36.         act.sa_handler    = on_signal;
  37.         oldact.sa_handler = NULL;
  38. // liste des signaux à bloquer pendant l'execution du handler
  39. sigemptyset( &act.sa_mask );
  40.         sigaddset  ( &act.sa_mask, SIGINT );
  41.         sigaction( SIGINT, &act, &oldact);
  42. }
  43. /*
  44. **
  45. **
  46. **
  47. */
  48. int main(int argc, char *argv[])
  49. {
  50. std::string cmd;
  51. sethandler();
  52. while(!std::cin.eof())
  53. {
  54.  std::cout << "> ";
  55.  std::cin  >> cmd;
  56.  if(std::cin.eof()) continue;
  57.  std::cout << "< " << cmd << std::endl;
  58. }
  59. std::cout << std::endl << "> bye (eof="<< std::cin.eof() << " )" << std::endl;
  60. return 0;
  61. }


 
 

Reply

Marsh Posté le 16-12-2003 à 17:41:53    

je comprends pas trop ton fonctionnement, cela dit
 
1) if(cin >> dawa)
au cas ou il se passe autre chose.
ensuite si c'est du eof, ilf aut clearer, et nettoyer un peu tout le bordel
std::cin.ignore(std::numeric_limits<int>::max(), '\n');

Reply

Marsh Posté le 16-12-2003 à 17:48:28    

je suis bien d'accord pour le nettoyage d'après la saisie, qui n'apparait pas dans ce code.
 
Ceci dit, le nettoyage du eof est bien fait dans le handler du SIGINT:

Code :
  1. std::cin.clear(std::ios::eofbit);


et quand j'éxecute cet exemple, le C^c fait bien passer dans le handler, qui fait le clear. Mais une fois revenu dans le processus pricipal, cin.eof() renvoie toujours true. Et c'est bien cela qui m'ennuie...
 

Reply

Marsh Posté le 16-12-2003 à 17:59:10    

et les autres champs il ressemblent à quoi ? avec un clear() ?

Reply

Marsh Posté le 16-12-2003 à 18:58:29    

Taz a écrit :

et les autres champs il ressemblent à quoi ? avec un clear() ?


 

Code :
  1. void on_signal( int signal )
  2. {
  3.         // ...
  4. std::cin.clear();
  5. }
  6. int main(int argc, char *argv[])
  7. {
  8.         // ...
  9. std::cout << "> eof="<< (std::cin.rdstate() && std::ios::eofbit)
  10.  << " good="<< (std::cin.rdstate() && std::ios::goodbit)
  11.  << " bad ="<< (std::cin.rdstate() && std::ios::badbit)
  12.  << " fail="<< (std::cin.rdstate() && std::ios::failbit)
  13.  << std::endl;
  14. }


 
résulat:  
eof=1 good=0 bad =1 fail=1


Message édité par SoWhatIn22 le 16-12-2003 à 18:58:47
Reply

Marsh Posté le 16-12-2003 à 19:12:47    

faut nettoyer le reste alors. le plus simple, c'est peut-être de ne changer le eof qui si c'est le seul problème.

Reply

Marsh Posté le 17-12-2003 à 08:16:25    

nettoyer quel reste? A priori, quand je fais std::cin.clear(), je me dis que tout devrait être nettoyé. Je me trompe? pour dire vrai, je ne vois pas bien comment nettoyer plus. me faut une nouvelle lessive qui nettoie encoire plus que l'actuelle, mais je sais pas laquelle...
 
 
 

Reply

Marsh Posté le 17-12-2003 à 09:38:52    

fais avec des & et des &&

Reply

Marsh Posté le 17-12-2003 à 09:38:52   

Reply

Marsh Posté le 17-12-2003 à 11:36:04    

Taz a écrit :

fais avec des & et des &&


désolé, je ne comprends pas ce que tu veux dire. Tu peux préciser?

Reply

Marsh Posté le 17-12-2003 à 12:27:16    

pas des && logiques mais des & binaires

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed