Mail Archives: cygwin-developers/1999/08/31/06:57:28
Chris Faylor wrote:
>
> On Fri, Aug 27, 1999 at 01:40:03PM +0400, Vadim Egorov wrote:
> >Hello,
> >
> >There is a problem with setjmp/longjmp/signals/exceptions that can be
> >demonstrated by the following code:
> >
...
> In this case, I suspect that setjmp itself is being interrupted so env
> is in an unknown state when the the signal handler uses it.
>
> -chris
Hello,
After digging around this problem I think that it concerns win32 SEH
mechanics. Following code shows the mutations of SEH frame
list while signals caused by exceptions are processed.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <windows.h>
#include <exceptions.h>
asm (".equ __except_list,0");
extern exception_list *_except_list asm ("%fs:__except_list");
static jmp_buf env;
int signo = SIGSEGV;
void print_seh(const char* where)
{
exception_list* p = _except_list;
printf("%s\n", where);
while ( p != (exception_list*)-1)
{
printf("\thandler: %08x\n", p->handler);
p = p->prev;
}
}
static void sig_handler(int sig)
{
print_seh("in signal");
longjmp(env, 1);
}
int main(int argc, char * * argv)
{
if ( setjmp(env) == 0 )
{
signal(signo, sig_handler);
print_seh("before signal");
*(char*)0 = 1;
}
else
{
print_seh("after signal");
}
return 0;
}
Program gives the following output:
before signal
handler: 6100b654
handler: 77f3b744
in signal
handler: 77f9667a
handler: 6100b654
handler: 77f3b744
after signal
handler: 77f9667a
handler: 6100b654
handler: 77f3b744
So when signal is invoked there is one extra exception handler
on the top of the list. I think it is added by Win32 SEH before
it begins to walk through SEH frame list.
Due to longjmp it remains there ever since and handles subsequent
exceptions. Looks like it returns ExceptionContinueExecution so
that program hangs at the next faulting instruction.
That's why some unwinding is required after longjmp if
exception handler is active. In this particular case simple
_except_list = _except_list->prev;
before longjmp is enough but in general case when other seh frames
can be involved the task is more complicated.
I think SEH unwinding should be performed in longjump based on
target esp value.
I would be grateful to here any comments about my conclusions
before I try to invent a fix for it.
Regards
Vadim
--
*********************************************
Vadim Egorov, 1C * ÷ÁÄÉÍ åÇÏÒÏ×,1C
egorovv AT 1c DOT ru * egorovv AT 1c DOT ru
*********************************************
- Raw text -