2013-01-05 4 views
1

Ceci est mon premier post ici, alors s'il vous plaît excuser tous les problèmes de mise en forme.STDIN semble être cassé après l'appel à "système" en invoquant mpiexec

J'ai un programme interactif qui génère des processus externes et surveille leurs E/S. Les choses fonctionnent bien jusqu'à ce que je génère quelque chose avec "mpiexec", après quoi STDIN semble rompre.

Je me rends compte que ce sera difficile à reproduire pour la plupart des gens, mais si quelqu'un voit quelque chose d'évident ou connaît ce problème .... s'il vous plaît aider!

Voici un extrait:

int main(...) 
{ 
    std::string choice; 
    while(std::getline(std::cin,choice)){ 
    if(!choice.empty()){ 
     if(choice == "Parallel"){ 
     system("mpiexec ./aprogram"); 
     } 
     if(choice == "Serial"){ 
     system("./aprogram"); 
     } 
     // Now the external process is done... so far, so good 
     std::cout << "Program is done. Press ENTER to continue." 
       << std::endl; 
     // This next line *works* if the external process was serial 
     // But *fails* when "mpiexec" was invoked 
     std::getline(std::cin,choice); 
     if(std::cin.eof()){ 
     std::cout << "STDIN has been closed." << std::endl; 
     exit(1); 
     } 
    } 
    } 
} 

J'ai essayé beaucoup de diverses choses, par exemple pipes, forking explicite, gestion des descripteurs méticuleuse. La chose la plus étrange est que si je saute et stdin stdin et restaure après le retour de "mpiexec", alors je n'ai plus EOF sur std :: cin, mais à la place, std :: getline (std :: cin, ...) ne bloque plus! Le programme va dans une boucle infinie en lisant zéro octet de std :: cin dans l'appel de std :: readline. Si, pendant que le processus externe s'exécute sous mpiexec, je superpose un tas de données dans std :: cin (par exemple en tapant), alors les appels suivants à std :: readline analysent correctement les lignes de données que j'ai bloquées là-bas, mais encore une fois ... une fois qu'il a fini de lire ces données, il continue juste dans une boucle infinie (c'est-à-dire ne pas bloquer sur std :: readline (std :: cin, ..) même s'il n'y a pas de données lire! Ugh. donc ennuyeux.

Toute aide est très apprécié.

Cheers!

+0

Quelle implémentation MPI utilisez-vous, sur quelle plateforme? –

+0

Nous utilisons actuellement des implémentations MPI MPICH (plusieurs versions, notamment MVAPICH, MPICH2 vanille et MPICH-MX) sur plusieurs plates-formes Linux différentes (dont la majorité sont basées sur S.L. ou CentOS). Je n'ai pas essayé avec OpenMPI, mais certaines applications de ce système intégré ne fonctionnent pas bien avec OpenMPI. Je crois que le problème doit être centré sur quelque chose que "mpiexec" fait avec STDIN. Je vais essayer d'obtenir un meilleur extrait afin qu'il puisse être facilement reproduit avec vanille mpich. – user1950175

+0

Je peux reproduire votre problème avec votre exemple de code et MPICH-3.0.1. Je regarde dedans. –

Répondre

1

Je pense que je fixe votre problème, pour moi, soit un appel à série ou Parallèle bloqué, et je pense que ce fut le std :: cin.eof() test,

std::getline(std::cin,choice); 
    if(std::cin.eof()){   
    td::cout << "STDIN has been closed." << std::endl; 
    exit(1); 
    } 

Cependant, la modification de ce à std :: cin.get(), fonctionne très bien pour les deux parallèles et série course .

if(std::cin.get()) { 
    std::cout << "STDIN has been closed." << std::endl; 
    exit(1); 
    } 

Fonctionne sur mon système.

0

Modifier: le rapport de bogue a moved to GitHub. OK, ce n'est pas vraiment une réponse, mais je n'ai pas assez de réputation pour commenter la question, apparemment.

Mes collègues et moi-même avons rencontré ce problème et nous l'avons retracé un peu. Vous devez sauter à travers tout un tas de cerceaux pour pouvoir ajouter un commentaire sur le mpich bug report, mais je ne voulais pas que mes découvertes disparaissent dans l'éther, alors je les ajoute ici. (Si quelqu'un qui lit ceci a une connexion mpich Trac, ce serait génial si vous pouviez ajouter cette information au ticket.)

Mpich semble effectivement avoir un bug où il place l'indicateur O_NONBLOCK sur le fichier stdout/stderr descripteurs de mpirun en modes communs. Ces paramètres persistent après les sorties mpirun. Cependant, ce bug ne fait généralement pas surface parce que bash a du code qui met à les indicateurs non bloquants de ses flux attachés après chaque commande qu'il exécute, si nécessaire.

Le code qui est directement responsable dans mpirun est dans alloc_fwd_hash dans src/pm/hydra/utils/sock.sock.c. Il est déclenché par le code dans des endroits comme src/pm/hydra/tools/bootstrap/external/external_common_launch.c dans la fonction HYDT_bscd_common_launch_procs, où il y a une étape d'enregistrement du démultiplexeur qui implique le rappel HYDT_bscu_stdio_cb qui appelle finalement la fonction alloc_fwd_hash. Il y a quelques autres morceaux de code similaires qui configurent aussi le rappel HYDT_bscu_stdio_cb et, en lisant le code, devraient déclencher le même problème. Je ne connais pas assez mpich pour comprendre quelle pièce est en faute, mais je crois qu'il est inapproprié pour mpich de définir des descripteurs de fichiers ATS en mode non bloquant.

Vous pouvez déclencher ce bogue en exécutant mpirun sous OS X à l'aide de la version Homebrew de bash. Le bash de Homebrew est la version 4.4, qui, pour des raisons pas tout à fait claires pour moi, ne semble pas activer le morceau de code qui efface le drapeau O_NONBLOCK. La version par défaut de bash sur OSX est la version 3, qui efface le drapeau, empêchant le bug de faire surface. La version Macports de Bash 4 fait également surface le bug.

Questions connexes