고아 프로세스 그룹에서 대화형 쉘은 무엇을 해야 합니까?

고아 프로세스 그룹에서 대화형 쉘은 무엇을 해야 합니까?

(다음의 제안을 바탕으로 유닉스에 다시 게시했습니다.https://stackoverflow.com/questions/13718394/what-should-interactive-shells-do-in-orphaned-process-groups)

간단한 질문은 쉘이 tty를 소유하지 않은 고아 프로세스 그룹에 있는 경우 어떻게 해야 하느냐는 것입니다. 하지만 이 긴 질문은 흥미롭기 때문에 읽어보시길 권합니다.

좋아하는 케이스를 사용하여 노트북을 휴대용 난방기로 바꾸는 재미있고 흥미로운 방법은 다음과 같습니다(당신이 이상한 사람이 아닌 이상).

#include <unistd.h>   
int main(void) {
    if (fork() == 0) {
        execl("/bin/bash", "/bin/bash", NULL);
    }
    return 0;
}

이로 인해 bash는 CPU를 100%로 고정합니다. zsh와 Fish는 동일한 작업을 수행하는 반면 ksh와 tcsh는 작업 제어에 대해 중얼거리다가 포기합니다. 이는 조금 더 나아지지만 훨씬 나아지지는 않습니다. 아, 그리고 이는 플랫폼 독립적인 공격자입니다. OS X와 ​​Linux가 모두 영향을 받습니다.

나의 (아마 잘못된) 설명은 다음과 같습니다: 서브쉘이 포그라운드에 있지 않다는 것을 감지했습니다: tcgetpgrp(0) != getpgrp(). 그래서 스스로 멈추려고 합니다: killpg(getpgrp(), SIGTTIN). 그러나 프로세스 그룹은 부모 프로세스(C 프로그램)가 리더였고 죽었기 때문에 고아가 되었으며, SIGTTIN고아로 보내진 프로세스 그룹은 버려졌습니다(그렇지 않으면 아무것도 다시 시작할 수 없습니다). 따라서 서브쉘은 멈추지 않고 여전히 백그라운드에 있으므로 모든 작업을 즉시 다시 수행합니다. 헹구고 반복하십시오.

내 질문은 명령줄 셸이 이 상황을 어떻게 감지하고 어떻게 해야 합니까?입니다. 두 가지 솔루션이 있지만 이상적이지는 않습니다.

  1. pid가 그룹 ID와 일치하는 프로세스에 신호를 보내보세요. 실패하면 ESRCH고아가 될 수도 있다는 뜻이다.
  2. 비차단 방식으로 바이트를 읽으려고 시도합니다 /dev/tty. 실패하면 EIO고아가 될 수도 있다는 뜻이다.

(이를 추적하는 문제는 다음과 같습니다.https://github.com/fish-shell/fish-shell/issues/422)

당신의 생각에 감사드립니다!

답변1

나는 귀하의 분석에 동의하며 프로세스 그룹이 고아인지 감지해야 하는 것처럼 들린다는 데 동의합니다.

tcsetattr또한 프로세스 그룹이 고아가 된 경우 반환을 의미합니다 EIO(그리고 SIGTT를 차단/무시하지 않습니다).유럽. read이는 터미널에 있는 방법보다 덜 침습적인 방법일 수 있습니다 .

다음 명령을 사용하여 재현할 수 있습니다.

(bash<&1 &)

그렇지 않으면 백그라운드에서 명령을 실행할 때 stdin이 /dev/null로 리디렉션됩니다.

(bash<&1 & sleep 2)

터미널에서 두 개의 쉘을 읽게 되므로 더욱 이상한 동작을 제공합니다. 이는 무시 SIGTTIN되고 새 프로세스가 감지되지 않으며 일단 시작된 후에는 더 이상 포그라운드 프로세스 그룹에 속하지 않습니다.

ksh93해결책은 나쁘지 않습니다. 포기하기 전에 (무한 대신) 최대 20번만 루프를 실행하십시오.

관련 정보