Выберите сбой с помощью программы C, но не оболочки

У меня есть родительский и дочерний процессы, и родитель может читать выходные данные дочернего процесса и отправлять их на вход дочернего процесса. Пока что все отлично работает со скриптами оболочки, тестирующими команды, которые вводят и выводят данные. Я только что протестировал с простой программой на C и не смог заставить ее работать. Вот программа на C:

#include <stdio.h>

int main( void ) {
  char stuff[80];
  printf("Enter some stuff:\n");
  scanf("%s", stuff);

  return 0;
}

Проблема с программой C состоит в том, что мой выбор не может прочитать от дочернего fd и, следовательно, программа не может завершиться. Вот бит, который делает выбор..

//wait till child is ready
fd_set set;
struct timeval timeout;

FD_ZERO( &set ); // initialize fd set
FD_SET( PARENT_READ, &set ); // add child in to set
timeout.tv_sec = 3;
timeout.tv_usec = 0;

int r = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
if( r < 1 ) { // we didn't get any input
    exit(1);
}

У кого-нибудь есть идеи, почему это происходит с программой на C, а не с оболочкой?

Редактировать: я должен указать, что дочерний процесс вызывает exec для аргумента, поэтому у меня нет доступа к нему после этой точки.

2 ответа

Решение

Проблема в том, что дочерний процесс полностью буферизует вывод, потому что он пишет в канал, а не в терминал. использование setvbuf форсировать буферизацию строки или небуферизованный режим, или добавить явный fflush ребенку после того printfили используйте программу unbuffer, которая поставляется вместе с Expect, чтобы обмануть libc дочернего процесса, заставляя его думать, что программа работает в интерактивном режиме.

Очистите свой стандартный вывод перед блокировкой ввода в программе C.

fflush(stdout);

В оболочке это часто неявно.

Вы также можете использовать setvbuf() отключить буферизацию (или включить буферизацию строки). Это должно быть вызвано перед записью любых данных:

setvbuf(stdout, NULL, _IONBF, 0)
Другие вопросы по тегам