This is the mail archive of the cygwin-developers@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: longjmp problem




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@1c.ru         *         egorovv@1c.ru
*********************************************


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]