Я не смог воспроизвести вашу ошибку SIGTTIN с предоставленным вами кодом, и это может быть связано только с точной последовательностью используемых вами команд GDB, но ваша программа перестала отвечать после того, как я дал ей следующий ввод:
ls &
ls
gdb показал, что этот оператор while
находится в бесконечном цикле:
void sig_handle(int sig){
int status;
while(waitpid(-1, &status, WNOHANG));
}
Добавление printf для более детального просмотра 1 :
void sig_handle(int sig){
int status, i, r;
for (i=0; i<5; i++) {
errno = 0;
r = waitpid(-1, &status, WNOHANG);
printf("waitpid returns %d errno %d\n", r, errno);
sleep(1);
}
}
и вывод:
waitpid returns 3672 errno 0
waitpid returns -1 errno 10
waitpid returns -1 errno 10
waitpid returns -1 errno 10
waitpid returns -1 errno 10
Таким образом, необходимо изменить логику так, чтобы цикл завершался, когда либо ожидался процесс, либо нет ожидающих процессов (или какой-либо другой)ошибка, которая не исчезнет, просто позвонив waitpid
снова).Справочная страница для waitpid сообщает:
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
в случае успеха возвращает идентификатор процесса ребенка, состояние которого изменилось;если был указан WNOHANG и один или несколько дочерних элементов (ren), указанных в pid, существуют, но еще не изменили состояние, возвращается 0.При ошибке возвращается -1.
ОШИБКИ
ECHILD Процесс, указанный в pid, не существует или не является дочерним по отношению к вызывающему процессу.
EINTR WNOHANG не был установлен и разблокированный сигнал или SIGCHLDбыл пойман.
EINVAL Аргумент options недействителен.
Поэтому я бы изменил код на:
void sig_handle(int sig){
int status;
while (waitpid(-1, &status, WNOHANG) == 0); // more precisely, break if r > 0 || r == -1
}
1 :printf в обработчике сигналов - плохая вещь (TM), но обычно он подходит для отладки.