독립된 프로세스 그룹에서 대화식 쉘은 어떻게해야합니까?


10

( /programming/13718394/what-should-interactive-shells-do-in-Olone-process-groups 의 제안에 따라 유닉스에 다시 게시 )

짧은 질문은 쉘이 tty를 소유하지 않는 고아 프로세스 그룹에있는 경우 어떻게해야합니까? 그러나 나는 긴 질문을 즐겁게 읽는 것이 좋습니다.

다음은 좋아하는 쉘을 사용하여 랩톱을 휴대용 공간 히터로 전환하는 재미 있고 흥미로운 방법입니다 (만약 tcsh 기괴한 사람이 아닌 경우).

#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. 에서 1 바이트의 비 차단 읽기를 시도하십시오 /dev/tty. 로 실패하면 EIO아마도 고아 일 것입니다.

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

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

답변:


4

귀하의 분석에 동의하며 프로세스 그룹이 고아인지 여부를 감지해야하는 것처럼 들립니다.

tcsetattrEIO프로세스 그룹이 고아 인 경우 에도 반환 됩니다 (SIGTT OU를 차단 / 무시하지 않는 경우) read.

다음을 사용하여이를 재현 할 수 있습니다.

(bash<&1 &)

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

(bash<&1 & sleep 2)

터미널에서 두 개의 셸을 읽음으로써 더 이상한 행동을하게됩니다. 무시 SIGTTIN되고 새 프로세스는 더 이상 포 그라운드 프로세스 그룹에없는 것으로 시작되면 감지하지 않습니다.

ksh93의 해결책은 그렇게 나쁘지 않습니다. 포기하기 전에 루프를 통해 최대 20 번 (무한 대신)까지 이동하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.