처리된 SIGINT가 하위 프로세스와의 파이프 통신에 영향을 줍니까?

처리된 SIGINT가 하위 프로세스와의 파이프 통신에 영향을 줍니까?

터미널에서 문구를 읽고 일련의 철자 바꾸기를 계산하는 대화형 C 프로그램이 있습니다. 또한 유지된 "입력 끝" 표시가 수신될 때까지 STDIN에서 줄을 읽고 버퍼링하고, 줄을 정렬하고, 열로 구성하고, STDOUT으로 보내는 Perl 프로그램도 있습니다. BSD/MacOS를 사용하는 C 프로그램은 popen()단일 양방향 파이프를 통해 Perl 프로그램을 시작하고 fprintf()모든 철자 바꾸기가 생성될 때까지 파이프에서 철자 바꾸기를 실행한 다음 getline()파이프에서 내보내서 형식화된 결과를 다시 읽고 인쇄합니다.

정상적인 상황에서는 잘 작동합니다. 그러나 C 프로그램에 SIGINT 핸들러를 추가하여 오랫동안 실행되는 단어 퍼즐을 중단하고 지금까지의 결과를 인쇄하고 더 많은 터미널 입력을 위해 루프를 돌릴 수 있었습니다. 핸들러는 파이프에 쓴 후 기본 프로그램이 확인하는 플래그를 설정합니다. 설정되면 charade 루프에서 벗어나 루프가 자연스럽게 끝난 것처럼 계속됩니다. 입력 끝 문자열을 보내고 형식이 지정된 결과를 다시 읽습니다.

문제가 발생하지 않습니다. fprintf입력의 끝은 일반 반환 코드를 얻지만 첫 번째 코드는 getlineEOF를 나타내는 null 포인터를 반환하므로 부분적인 결과를 얻지 못합니다. C 프로그램은 예상대로 정상적으로 계속됩니다.

처리된 SIGINT가 열려 있는 파이프에 영향을 준다는 내용을 문서에서 찾지 못했지만 Perl 프로그램에서 어떤 것도 수신하지 못하게 하는 다른 어떤 것도 생각할 수 없습니다.

답변1

신호는 SIGINT포그라운드 프로세스 그룹의 모든 프로세스로 전송됩니다. 포그라운드 프로세스 그룹에는 일반적으로 popen실행 중인 모든 프로세스가 포함됩니다.

/* popen.c */
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void poke(int unused) { fprintf(stderr, "sigint - C\n"); }
int main(void) {
    FILE *fh;
    signal(SIGINT, poke);
    fh = popen(
      "exec perl -e '$SIG{INT}=sub {warn q{ouch}};sleep 1 while 1'",
      "r+");
    if (!fh) abort();
    while (1) sleep(1);
    return 42;
}

이는 다음을 통해 확인할 수 있습니다.

$ make popen
$ ./popen
^Csigint - C
ouch at -e line 1.
^Csigint - C
ouch at -e line 1.
^\Quit

따라서 모든 프로그램은 이 신호를 처리해야 하며 그렇지 않으면 터미널에서 신호를 끌 수 있습니다. 세부 사항은 언어에 따라 다르지만 Perl의 신호를 무시하려면 간단히 무시하면 됩니다.

$SIG{INT} = "IGNORE";

또 다른 옵션은상위 프로세스의 블록 신호, 후속 프로그램은 자체 신호 처리기를 설치할 수 있습니다.

ISIG또 다른 옵션은 터미널에서 플래그를 비활성화하는 것입니다. 이 경우 control+는 c신호를 전경 프로세스 그룹으로 보내지 않고 대신 일부 프로그램에서 문자를 읽을 수 있게 합니다. 자세한 내용은 매뉴얼 페이지를 참조하십시오 termios(맨 페이지 섹션은 운영 체제에 따라 다릅니다). Curses와 같은 인터페이스가 아마도 일반적인 인터페이스일 것입니다. 대신에 tcsetattr(3)비활성화하기 위한 적절한 호출을 할 수도 있습니다 ISIG.

#!/usr/bin/env perl
# example script showing how control+c can be read as a key
use strict;
use warnings;
use Curses;
initscr;
noecho;
raw;    # disables ISIG, among other things
while (1) {
    my $ch = getchar() // die "getchar failed??";
    last if $ch eq 'q';
    move 0, 0;
    clrtoeol;
    addstring sprintf "key: %vx", $ch;
}
endwin;

key: 3이는 +를 누를 control때 표시되어야 합니다 . c신호는 포그라운드 프로세스 그룹으로 전송되지 않습니다. 종료 하려면 입력하세요 q.

관련 정보