2014-09-20 4 views
1

SIGSEGV, SIGILL에 대한 신호 처리기를 설정하고 전체 프로세스를 종료하는 대신 불쾌한 스레드를 종료하고 어쩌면 모니터링 스레드가 불평 할 수 있도록 다른 플래그를 설정하는 몇 가지 다른 신호를 설정하려고합니다. 실. 이 작업을 수행 할 수있는 안전한 방법이 있는지 확신하지 못합니다. Pthreads는 다른 스레드를 취소 할뿐만 아니라 현재 스레드를 종료하는 기능을 제공하는 것으로 보이지만, 잠재적으로 이들을 종료시 처리기로 호출합니다. 그렇지 않더라도 비동기 신호가 안전하지 않은 상황이 많은 것처럼 보이지만 그러한 상황을 피할 수는 있습니다. 스레드를 파괴하는 호출 할 수있는 저수준 함수가 있습니까? 비동기 신호 안전 방식으로 내 자신의 데이터 구조를 수정하고 mutex를 얻지 않는다고 가정하면 pthread/SIGSEGV에서 종료되는 스레드에 의해 일관성없는 상태로 남을 수있는 다른 전역 데이터 구조가 있습니까? malloc이 마음에 들지 만, malloc 자체는 libc가 버그가 없다면 SIGSEGV/SIGILL해서는 안됩니다. POSIX는 매우 보수적 인 것으로 알고 있으며, 아무런 보장도하지 않습니다. 실제로이 작업을 수행 할 수있는 한 행복합니다. 포크는 옵션이 아닙니다, btw.신호 처리기에서 스레드를 올바르게 종료하는 방법은 무엇입니까?

+2

별도의 프로세스를 사용하십시오. 프로세스의 모든 스레드는 동일한 메모리 공간에 액세스 할 수 있으므로 세그 폴트가 발생하는 지점에 도달하기 전에 내부 데이터 구조 (예 : malloc 및 co)가 엉망이 될 수 있습니다. 스레드 대신 프로세스를 사용하면 적절한 구분을 제공합니다. –

+0

'malloc'은 절대적으로'malloc'에 버그가없는'SIGSEGV'를 사용합니다. 이것은 프로그램의 잘못입니다. –

답변

2

SIGSEGV/SIGILL/etc. 자신의 코드에서 발생합니다 신호 처리기가 비동기 신호 컨텍스트에서 실행되지 않습니다 (기본적으로 동기 신호이지만 표준 라이브러리 함수 내에서 발생한 경우 여전히 AS 컨텍스트가 됨)이므로 합법적으로 pthread_exit 신호 처리기에서.

  • SIGSEGV/SIGILL/등 : 그러나, 여전히 반신 반의하는 이러한 관행을 문제가 있습니다. raise, kill, pthread_kill, sigqueue 등을 통해 생성하지 않으면 동작이 정의 된 프로그램에서 절대로 발생하지 않습니다.이 특수한 경우에는 이 비동기 신호 인이됩니다. 그렇지 않으면의 정의되지 않은 동작 인 을 나타내는 프로그램을 나타냅니다. 프로그램에서 정의되지 않은 동작을 호출하면 모든 베팅이 해제됩니다. UB는 특정 스레드 나 시간의 특정 시퀀스와 분리되지 않습니다. 프로그램에 UB가 있으면 전체 출력/동작이 의미가 없습니다.

  • 프로그램의 상태가 손상된 경우 (예 : free 이후의 액세스로 인해 잘못된 포인터, 버퍼 오버 플로우 등) 첫 번째 오류 액세스가 표준 라이브러리의 일부에서 발생합니다 예 : malloc)를 사용하십시오. 이 경우 신호 처리기는 AS 안전 컨텍스트에서 실행되며 pthread_exit을 호출 할 수 없습니다. 물론 프로그램에는 이미 UB가 있지만 (위의 요점 참조), 문제가 아닌 것처럼 보이더라도 여전히 문제가 될 수 있습니다.

프로그램에서 이러한 종류의 충돌이 발생하면 신호 처리기로 패치를 시도하지 말고 원인을 찾아 수정해야합니다. Valgrind는 당신의 친구입니다. 그렇게 할 수 없다면 가장 좋은 방법은 충돌하는 코드를 별도의 프로세스로 분리하여 동일한 프로세스에서 충돌하는 코드가 아닌 비동기식으로 충돌 한 경우 발생하는 상황을 추론 할 수있는 것입니다 (여기서 코드의 동작에 대한 추론은 유효하지 않습니다). 일단 그것이 충돌하는 것을 안다).

+0

내 질문에 완벽하게 대답합니다.이것은 실제로 물건을 컴파일하고, dlopen하고, C로 livecoding하는 코드를 실행하는 시스템을위한 것입니다. 그래서 실수는 피할 수 없으며 최소한 나쁜 것을하기위한 것입니다. 프로그램이 기본적으로 임의의 메모리 위치를 수행 할 수 있기 때문에 오류 스레드가 나머지를 가져 오지 않을 것이라고 보장 할 수있는 방법이 없습니다. 하지만 적어도 여기에 나오는 결과는 좋은 스레드가 양호하게 유지되고 코드를 수정하고 프로그램을 중단하지 않고 다시 컴파일 할 수 있다는 것입니다. – user2040142

+0

이런 종류의 사용 사례의 경우 실제로 코드를 별도의 프로세스에서 실행해야합니다. 이런 종류의 접근법으로 성공할 수있는 유일한 방법은 실행중인 코드가 주 프로그램에서 공유 데이터를 거의 또는 전혀 액세스하지 않는 경우입니다 (버퍼 오버플로가 주 프로그램의 데이터를 지울 수도 있음) , 그러나 그러한 사용 사례는 정확히 어쨌든 별도의 프로세스로 쉽게 이동할 수 있습니다. 별도의 프로세스로 이동하기 어려운 경우는 공유가 많은 경우이며, 버그가있는 모듈이 전체 프로그램 상태를 휴지통으로 처리하는 경우입니다. –

관련 문제