segfault 프로그램의 파이프 출력

segfault 프로그램의 파이프 출력

프로그램(특히 tetex 3.0의 일부)을 호출하는 스크립트가 있는데 ttf2afm때로는 세그폴트가 발생하고 때로는 그렇지 않습니다. 나에게 필요한 정보는 항상 인쇄되어 있습니다.앞으로세그폴트가 발생하지만 파이프 리디렉션이 실패하는 것을 방지하고 프로그램이 실패할 때 파이프에 아무 것도 출력하지 않는 데 문제가 있습니다.

trueFIFO를 통해 리디렉션을 시도하고 끝에 프로세스를 래핑하고 셸 함수에서 실행하고 로 래핑했지만 sh -c스크립트에서 프로세스 출력을 허용하지 않는 것 같습니다.아무것, 리디렉션 또는 기타 - stderr도 아닙니다.

나는 그것이 명령줄에서 완벽하게 제공할 수 있기 때문에 출력할 수 있다는 것을 알고 있지만 어떤 이유로 스크립트에서는 제공할 수 없습니다.

제 질문은, 스크립트가 세그폴트 사실을 무시하고 출력을 제공할 수 있는 방법이 있습니까?입니다.

BASH 4.1.10(2) 릴리스를 실행 중입니다.

답변1

프로그램은 효율성을 높이기 위해 출력을 버퍼링하는 경우가 많습니다. 즉, 메모리 영역(버퍼라고 함)에 출력을 축적하고, 버퍼가 가득 찼을 때나 프로그램의 특정 중요한 지점에서만 실제로 출력을 출력합니다. 프로그램이 정상적으로 종료되면 출력 버퍼를 플러시합니다(즉, 버퍼에 남아 있는 모든 데이터를 인쇄합니다). 세그폴트가 발생하면 버퍼의 내용이 손실됩니다.

프로그램의 출력이 터미널에 연결될 때(일반 파일이나 파이프가 아닌) 동작이 다르기 때문에 터미널에서 직접 프로그램을 실행할 때는 이 효과를 관찰할 수 없습니다. 터미널에서 기본 동작은 각 줄 끝에서 버퍼를 플러시하는 것입니다. 따라서 세그먼트 오류가 발생하기 전에 프로그램에서 생성된 모든 전체 라인을 볼 수 있습니다.

프로그램을 터미널에서 강제로 실행하고 해당 출력을 수집할 수 있습니다. 가장 쉬운 방법은 달리는 것입니다script. 해결해야 할 걱정거리가 많이 있습니다.

  • script나중에 제거해야 하는 헤더 행을 전사 파일에 추가합니다.
  • script명령의 상태 코드는 반환되지 않으므로 segfault 또는 기타 오류에 대해 알고 싶다면 어딘가에 저장해야 합니다.
  • script일반 출력과 오류 출력이 모두 발생합니다. 오류 출력을 별도의 파일에 저장하는 것이 좋습니다.
export FONT="foo"
script -q -c '
    ttf2afm "$FONT.ttf" 2>"$FONT.ttf2afm-err";
    echo $? >"$FONT.ttf2afm-status"
' "$FONT.ttf2afm-typescript"
tail -n +2 <"$FONT.ttf2afm-typescript" >"foo.afm"
rm "$FONT.ttf2afm-typescript"
if [ "$(cat "$FONT.ttf2afm-status")" -ne 0 ]; then
  echo 1>&2 "Warning: ttf2afm failed"
  cat "$FONT.ttf2afm-err"
fi

답변2

계속해서 더듬고 더듬어 본 끝에 마침내 알아냈습니다. 해결책은 약간 복잡합니다.

(trap 'true' ERR; exec ttf2afm "$FONT") |
grep ...

아무래도 서브쉘 프로세스를 exec잡아낸 오류가 ttf2afm인계받아 세그폴트 발생 여부가 중요하지 않은 환경에서 실행되게 된 것 같습니다.

포괄적인 신호를 포착하면 서브쉘이 죽는 것을 방지하고 프로그램이 실패할 때 ERR메인 스크립트에 신호를 보냅니다 (이런 일이 발생하면 메인 스크립트가 즉시 종료됩니다).

유일한 문제는커널 자체스택 추적 쓰레기를 출력합니다콘솔 장치에 직접 연결프로세스 세그폴트가 발생하면 [내가 아는 한] 출력되는 것을 방지할 방법이 없지만 stdout이나 stderr에는 영향을 주지 않으므로 문제가 되지 않습니다.

관련 정보