Выберите сбой с помощью программы 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)