Я пишу мини-оболочку (нет, не для школы: P; для собственного удовольствия), и теперь большинство основных функций выполняются, но я застреваю при попытке обработать SIGTSTP.
Предположительно, когда пользователь нажимает Ctrl+Z
, SIGTSTP должен быть отправлен в процесс Foreground оболочки, если он существует, и Shell должна продолжать нормально.
После создания каждого процесса (если это процесс Foreground), следующий код ждет:
if(waitpid(pid, &processReturnStatus, WUNTRACED)>0){//wait stopped too
if(WIFEXITED(processReturnStatus) || WIFSIGNALED(processReturnStatus))
removeFromJobList(pid);
}
И я обрабатываю сигнал следующим образом:
void sigtstpHandler(int signum)
{
signum++;//Just to remove gcc warning
pid_t pid = findForegroundProcessID();
if(pid > -1){
kill(-pid, SIGTSTP);//Sending to the whole group
}
}
Что происходит, когда я нажимаю Ctrl+Z
, дочерний процесс действительно приостанавливается (используя ps -all
для просмотра состояния процессов), но моя оболочка зависает в waitpid
, она никогда не возвращается, хотя я прошел WUNTRACED
, который, насколько я понял, должен возвращать waitpid
, когда процесс также остановлен.
Так что я мог сделать неправильно? или я неправильно понял поведение waitpid?
Примечания:
-findForegroundProcessID() возвращает правый pid; Я дважды проверил это.
- Я меняю каждую группу процессов, когда сразу после я fork
-Handling Ctrl+C
работает отлично!
-Если я использую другой терминал для отправки SIGCONT после того, как моя оболочка зависает, дочерний процесс возобновляет свою работу, а оболочка пожинает его в конце концов.
-Я улавливаю SIGTSTP, который, насколько я читал (и тестировал), можно поймать.
-Я попытался использовать waitid вместо waitpid на всякий случай, проблема сохранилась.
EDIT:
void sigchldHandler(int signum)
{
signum++;//Just to remove the warning
pid_t pid;
while((pid = waitpid(-1, &processReturnStatus, 0)) > 0){
removeFromJobList(pid);
}
if(errno != ECHILD)
unixError("kill error");
}
Мой обработчик SIGCHLD.