Operating System - HP-UX
1820880 Members
3577 Online
109628 Solutions
New Discussion юеВ

Re: Hangup during regeneration of the signal

 
SOLVED
Go to solution
Adam J Markiewicz
Trusted Contributor

Hangup during regeneration of the signal

Hi. I have a simple problem. When the same signal is generated again from the function that is installed as a handler to this signal, process thakes 100% CPU. Tested on HP 10.20 and HP 11.
Try the code, like:

void BadAccess() {
char *ptr = 0xABADC0DE;
if( *ptr ) { // SIGSEGV
}
}

void handler()
{
BadAccess();
}

int main( void )
{
sigset( SIGSEGV, handler );
BadAccess();

return 0; //never touched
}

I don't know what should be done (only killing with core seems to be logical), but definetly consuming 100% CPU forever is not the bes idea.
Is it bug in kernel, compiler (aCC), libraries? Could anyone chek it if it's happening always?

Thanks in advance.
I do everything perfectly, except from my mistakes
5 REPLIES 5
Adam J Markiewicz
Trusted Contributor

Re: Hangup during regeneration of the signal

Few words more, before someone tells me I'm imbecile. :)

I know that during execution of handler the signal is blocked (and I think this causes the problem). Someone could suggest that the signal is generated, but blocked, so it waits for execution of the handler to be finished and then calls it again. So the handler is called over and over again and I get 100% CPU usage.

No.

I've checked it several times. The first call of the handler never returns. It is stopped at bad memory access forever.

I cannot change the handler. Its not mine it is a part of DCE library which I have to use. I don't know what this handler should do. Actually I think that it is idiotic to try to do something more when process corrupts memory, but DCE is done that way and I cannot do anything about it.

Is it possible that nobody had that problem before me? Is it so specific? Guyz, please help.
I do everything perfectly, except from my mistakes
Mike Stroyan
Honored Contributor

Re: Hangup during regeneration of the signal

The problem is caused by causing a SIGSEGV when the signal is blocked. If you block a synchronous signal then the system will retry the instruction that caused the signal. If that signal is SIGSEGV or SIGBUS or SIGILL, then the process will repeat the same instruction again and again, making no forward progress.
The answer is don't block those signals. If you write a signal handler for those signals then it should be very cautious. It should either reset the signal handler or unblock the signal as soon as you enter the handler. If you switch to sigaction instead of sigset you can use the SA_RESETHAND or SA_NODEFER flags to make that change before even entering your signal handler.
If you leave the handler active and use SA_NODEFER you should have a very early check for recursion to avoid infinite recursion.
Adam J Markiewicz
Trusted Contributor

Re: Hangup during regeneration of the signal

Hi, Mike, thanks for assistance

If I undestood right I would have to reinstall DCE handler with another flag, namly SA_NODEFER?
And if the situation is reproduced my process will blow up with stack overflow? (By the way - will it work correctly in multithread?)
Well this is a sort of solution, but I'm not sure how and when DCE installs its handlers. It is possible that it decides to make reinstallation after my play with it (as a result to some event for example). And I'm not willing to poll it periodically.
However the idea is worth to try.

I thought that, as it is probabilly easy for OS to discover that process stops inside handler with blocked signal, as it is not delayed for the next execution of the handler, but it is a real stop, there is somewhere available some sort of patch to always generate core in such situation.
That would solve simmilar problem completelly with every handler and every signal.

Luckilly for me one of my colegues found a patch on DCE library that allows process to generate core when SIGSEGV. Again, I don't know how they did it (I guess they removed that idiotic handler completelly), but this makes me happy.

Thanks again.
I do everything perfectly, except from my mistakes
Mike Stroyan
Honored Contributor
Solution

Re: Hangup during regeneration of the signal

I dug around in some of the DCE patch documentation. DCE is trying to catch signals like SIGSEGV to allow the signals to be handled by TRY/RECOVER blocks. Apparently it won't plug in a signal handler if there is already a handler plugged in before DCE gets to it.

Perhaps the best fix for DCE applications is to have all dangerous code, (aka ALL CODE),
inside some TRY/RECOVER block.
Adam J Markiewicz
Trusted Contributor

Re: Hangup during regeneration of the signal

Thanks again, Mike

That was extremly precise description, I'm impressed how people are willing to help on this forum. I appreciate the time you've spent for me in this docs, you definetly earned the points.

By the way, if someone had simmilar problem I've found another tepmorar sollution. I patched sigset() and sigaction() (with help of information I've found in manuals for dlsym() and how to patch malloc() and free() ).
If someone tries to install 'permanent' handler (SA_RESETHAND not set) I install my special handler with SA_RESETHAND set. This special handler calls the original handler and at the end reinstalls itself, again with SA_RESETHAND set.

Why all this stuff?
During execution of the original handler, the SIG_DFL is set, so if it is SIGSEGV and is regenerated from the handler core will be dumped.

Why I dont like this either?
Signal handlers are shared among threads. If, during execution of the handler by one thread SIGSEGV will be generateg by another thread it will find SIG_DFL handling. But that signal launch the original handler - mayby it is correct situation, predefined by the programmers and for this the handler was installed. If I didn't use threads this could be accepted, but how can you ommit threads in DCE?

And the last thing is:
I still think it is idiotic to use SIGSEGV handler for any usefull work. It should be left exclusivelly for program failures. Another thing is that the handlers are shared among all threads (however executed by every thread independly), so using it to check if it was called from any specific block of code (like TRY/RECOVER) is not the cleanest way. Especially because DCE was designed to be multithread.


Mayby I shouldn't write it as an answer to my queston. :)
I do everything perfectly, except from my mistakes