STDIN кажется сломанным после вызова системы, вызывающей mpiexec

Это мой первый пост здесь, поэтому, пожалуйста, извините за проблемы с форматированием.

У меня есть интерактивная программа, которая порождает внешние процессы и отслеживает их ввод-вывод. Все работает нормально, пока я не создам что-то с помощью «mpiexec», после чего STDIN, похоже, сломается.

Я понимаю, что это будет трудно воспроизвести для большинства людей, но если кто-то увидит что-то очевидное или знает об этой проблеме... пожалуйста, помогите!

Вот фрагмент:

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);
       }
     }
  }
} 

Я пробовал много разных вещей, например. каналы, явное разветвление, тщательное управление дескрипторами. Самое странное, что если я отключу и сохраню stdin, а затем восстановлю его после возврата «mpiexec», то я больше не получаю EOF на std::cin, а вместо этого std::getline(std::cin,... ) больше не блокирует! Программа переходит в бесконечный цикл, считывая нулевые байты из std::cin в вызове std::readline.

Если во время работы внешнего процесса под управлением mpiexec я засуну кучу данных в std::cin (например, набрав), то последующие вызовы std::readline правильно разберут строки данных, которые я туда засунул, но снова... как только он закончит чтение этих данных, он просто продолжит работу в бесконечном цикле (т.е. не блокируется на std::readline(std::cin,..), даже если нет данных для чтения! Тьфу. Так раздражает.

Любая помощь приветствуется.

Ваше здоровье!


person user1950175    schedule 05.01.2013    source источник
comment
Какую реализацию MPI вы используете, на какой платформе?   -  person Dave Goodell    schedule 07.01.2013
comment
В настоящее время мы используем реализации MPI на основе MPICH (несколько разновидностей, включая MVAPICH, vanilla MPICH2 и MPICH-MX) на нескольких различных платформах на базе Linux (большинство из которых основаны на SL или CentOS). Я не пробовал с OpenMPI, но некоторые приложения в этой интегрированной системе плохо работают с OpenMPI. Я считаю, что проблема должна быть сосредоточена вокруг того, что mpiexec делает со STDIN. Я постараюсь получить лучший фрагмент, чтобы его можно было легко воспроизвести с помощью vanilla mpich.   -  person user1950175    schedule 08.01.2013
comment
Я могу воспроизвести вашу проблему с вашим примером кода и MPICH-3.0.1. Я изучаю это.   -  person Dave Goodell    schedule 08.01.2013
comment
Выдающийся. Большое спасибо, Дэйв.   -  person user1950175    schedule 10.01.2013
comment
Пока нет исправления, но похоже, что на самом деле он не закрывает базовый файловый дескриптор. Вместо этого вызов read для fd 0 возвращает EAGAIN, как если бы стандартный ввод был сделан неблокирующим. Я еще не нашел, где бы мы это делали, но здесь определенно происходит что-то смешное. Мы продолжим смотреть на это.   -  person Dave Goodell    schedule 11.01.2013
comment
Спасибо, Дэйв. Я также пытался установить блокировку дескриптора, но безрезультатно. Я тоже вернусь к просмотру этого снова ... после того, как уберу этот другой хлам с моей тарелки.   -  person user1950175    schedule 11.01.2013
comment
Я не смог понять, в чем проблема, за разумное время. Чтобы мы не забыли о проблеме, я подал заявку в нашу местную систему отслеживания ошибок: trac.mpich.org/projects/mpich/ticket/1782   -  person Dave Goodell    schedule 16.01.2013
comment
Еще раз спасибо, Дэйв. Я ценю его.   -  person user1950175    schedule 18.01.2013


Ответы (1)


Я думаю, что исправил вашу проблему, для меня либо вызов Serial, либо Parallel заблокирован, и я думаю, что это был тест std::cin.eof(),

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

Однако изменение этого на std::cin.get() отлично работает как для параллельного, так и для последовательного запуска.

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

Работает в моей системе.

person Andrew Davis    schedule 09.04.2013