我想使用sigaction設置一個異常處理程序。它適用於第一個例外。但是,在第一個異常之後不會調用sigaction處理程序,並且第二個信號發生時程序會突然結束。爲什麼我的信號處理程序(引發異常)不會觸發多次?
#include <iostream>
#include <signal.h>
#include <exception>
#include <string.h>
typedef void (*SigactionHandlerPointer)(int iSignal, siginfo_t * psSiginfo, void * psContext);
using namespace std;
void SigactionHookHandler(int iSignal, siginfo_t * psSiginfo, void * psContext)
{
cout << "Signal Handler Exception Caught: std::exception -- signal : " << iSignal << " from SigactionHookHandler()" << endl;
throw std::exception();
}
class A
{
public:
A() {}
virtual ~A() {}
virtual void fnct1();
virtual void fnct2() { fnct3(); }
virtual void fnct3() { fnct4(); }
virtual void fnct4();
};
void
A::fnct1()
{
try {
fnct2();
}
catch(std::exception &ex) {
cerr << "Signal Handler Exception Caught" << endl;
}
catch (...)
{
cerr << "Unknow Exception Caught: " << endl;
}
}
void
A::fnct4()
{
*(int *) 0 = 0; // Access violation
}
int main()
{
struct sigaction oNewSigAction;
struct sigaction oOldSigAction;
memset(&oNewSigAction, 0, sizeof oNewSigAction);
oNewSigAction.sa_sigaction = SigactionHookHandler;
oNewSigAction.sa_flags = SA_SIGINFO;
int iResult = sigaction(SIGSEGV, &oNewSigAction, &oOldSigAction);
cout << "sigaction installed handler with status " << iResult << endl;
A * pA = new A();
cout << "Next message expected is : <<Signal Handler Exception Caught: std::exception>> to pass this test" << endl;
pA->fnct1();
// Second exception will never be call the sigaction handler.
cout << "Next message expected is : <<Signal Handler Exception Caught: std::exception>> to pass this test" << endl;
pA->fnct1();
return 0;
}
我使用GNU GCC和Intel編譯器。我使用了-fnon-call-exceptions選項。建議的補丁有效。但請注意,我更改了sigprocmask(SIG_UNBLOCK,&x,NULL);到pthread_sigmask(SIG_UNBLOCK,&x,NULL);因爲我有一個多線程應用程序。但我仍然感到困惑。 gcc-lib手冊指出:「......在任何情況下,當處理程序返回時,系統恢復進入處理程序之前的掩碼......」如果我評論throw std :: exception( )在原始代碼中,然後在調用信號處理程序之後,我確實返回到原始異常 – 2011-05-03 13:15:59
(從以前的評論中繼續...),並且信號處理程序被一次又一次調用...因此,我沒有想到必須自己解除信號。我錯過了什麼? – 2011-05-03 13:19:05
@Guy B:所以它看起來手冊是錯誤的,當它說「在任何情況下」,雖然人們可能會認爲拋出異常與「返回」不一樣。 FWIW,這再現了我在gcc 3.4.6,gcc 4.4.1,gcc 4.5.2和gcc 4.6.0。 – Cubbi 2011-05-03 14:26:58