프로세스가 무제한 환경에서 실행되고 있다고 가정해 보겠습니다.
(
ulimit ... -v ... -t ... -x 0 ...
./program
)
프로그램이 종료됩니다.
이유는 다양할 수 있습니다. 단순한 세그먼트 오류로 인해 메모리/시간/파일 제한이 초과되었거나 반환 코드 0으로 정상적으로 종료되는 경우도 있습니다.
프로그램을 수정하지 않고 프로그램이 종료된 이유를 어떻게 확인할 수 있나요?
PS 나는 "바이너리가 주어졌을 때"를 의미했습니다. 어쩌면 일부 래퍼(ptrace-ing 등)가 도움이 될 수 있을까요?
답변1
일반적으로 불행하게도 나는 당신이 할 수 없다고 생각합니다. (일부 운영 체제에서는 이 기능을 제공할 수 있지만 어느 운영 체제에서 지원하는지 모르겠습니다.)
리소스 제한 참조 문서:getrlimit
POSIX 2008부터.
CPU 제한을 예로 들어 보겠습니다 RLIMIT_CPU
.
- 프로세스가 소프트 제한을 초과하면 전송됩니다.
SIGXCPU
- 프로세스가 하드 제한을 초과하면 간단한 메시지가 표시됩니다.
SIGKILL
wait()
프로그램에서 할 수 있다면 프로그램이 종료되었는지 알 수 있습니다 SIGXCPU
. 하지만 SIGKILL
엄격한 제한 위반에 대한 파견과 외부에서 보내는 평범한 살인 사이의 차이를 구분할 수 없습니다 . 게다가 프로그램이 처리하면 XCPU
외부에서도 볼 수 없습니다.
에 대해서도 마찬가지입니다 RLIMIT_FSIZE
. 프로그램이 처리하지 못하는 경우 SIGXFSZ
상태를 통해 확인할 수 있습니다. wait()
그러나 파일 크기 제한을 초과하면 제한을 다시 테스트하려는 추가 I/O가 수신될 뿐이며 EFBIG
이는 프로그램에서 내부적으로 처리됩니다(또는 불행하게도 처리되지 않음). 프로그램이 SIGXFSZ
위와 동일하게 이를 처리하는 경우 - 사용자는 이를 알 수 없습니다.
RLIMIT_NOFILE
? 글쎄, 신호도 못 받는구나. open
친구들과 함께 쇼로 돌아오세요 EMFILE
. 다른 어떤 것의 방해도 받지 않으므로 이 경우 인코딩이 어떤 방식으로 실패하더라도 실패(또는 실패)합니다.
RLIMIT_STACK
? 너무 오래 SIGSEGV
되어서 다른 원인과 구별할 수 없습니다. (이것이 프로세스를 죽인 원인이라는 것을 상태를 통해 알 수 있습니다 wait
.)
RLIMIT_AS
RLIMIT_DATA
make만 하고 malloc()
다른 일부는 실패하기 시작합니다(또는 SIGSEGV
Linux에서 스택을 확장하려고 할 때 AS 제한에 도달하면 수신합니다). 프로그램이 잘 작성되지 않으면 무작위로 실패할 수 있습니다.
간단히 말해서, 일반적으로 실패는 프로세스 종료의 다른 이유와 크게 다르지 않으므로 확신할 수 없거나 프로그램에서 완전히 처리할 수 있습니다. 이 경우 진행 여부/언제/방법을 결정합니다. 반면 당신은 외부에서 온 것이 아닙니다.
내가 아는 한, 당신이 할 수 있는 최선은 프로그램을 분기하고 기다린 다음 다음과 같은 코드를 작성하는 것입니다.
- 감지할 종료 상태를 확인합니다
SIGXCPU
(SIGXFSZ
AFAIK, 이러한 신호는 리소스 제한 문제에 대해 운영 체제에서만 생성됩니다). 특정 요구 사항에 따라 리소스 제약과 관련이 있다고 가정할 수도 있지만SIGKILL
이는SIGSEGV
다소 무리한 일입니다. getrusage(RUSAGE_CHILDREN,...)
다른 구현에 대한 팁을 얻으려면 구현에서 무엇을 얻을 수 있는지 확인하세요 .
ptrace
여기서는 OS별 도구( Linux 또는 Solaris의 도구 )나 디버거 유형의 기술이 도움이 될 수 있지만 dtrace
이는 특정 구현과 더 관련이 있습니다.
(나는 내가 전혀 모르는 마법 같은 질문에 다른 누군가가 대답해 줄 수 있기를 바랍니다.)
답변2
나는 현재 같은 문제에 대해 몇 가지 작업을 수행 중입니다. 부분적으로 해결이 되었습니다. 나는 사용했다심사하위 시스템. [1]에서 작업을 추적할 수 있습니다.