#include  <stdio.h>
#include  <signal.h>
#include  <setjmp.h>

jmp_buf  g_my_jump_buffer;

bool try_signal (int sig)
{
    int result;

    result = setjmp(my_jump_buffer, sig);
    printf ("setjmp(): resutl %d \r\n", result);
    if (sig==result)
        return true;
    return false;
}

void signal_handler (int sig)
{
    printf ("signal_handler(%d) \r\n", sig);
    longjmp (g_my_jump_buffer, sig);
}

int main (void)
{
    unsigned int* p = (unsigned int*)0xffffffff;

    signal (SIGBUS, signal_handler);

    while (1)
    {    
        if (try_signal (SIGBUS)==0)
        {
            printf ("no signal \r\n");
            *p = 0x00000001;
        }
        else
        {
            printf ("signal \r\n");
        }
    }
    return 0;
}

이런식으로 setjmp를 사용하면 프로그램이 망한다.
setjmp시 현재 스택 포인터를 저장하는 역할을 하기 때문에 위에 처럼 setjmp를 랩핑해서 함수를 호출하여 사용하면
1. 위에 main함수에서 try_signal()을 호출하고 
2. signal이 발생되어서 signal_handler()를 거쳐서
3. 다시 setjmp()함수 위치로 복귀하려 했을때 
   이전 try_signal()이 호출 되어서 저장했던 스택포인터는 
   이전 try_singal()가 main()함수로 복귀를 했으므로 저장했던 해당 스택포인터가 유효 하지 않다.
랩핑해서 사용하고 싶을땐 아래와 같이 inline함수로 구현하던가 매크로로 구현해야한다.

#include  <stdio.h>
#include  <signal.h>
#include  <setjmp.h>

jmp_buf  g_my_jump_buffer;

inline bool try_signal (int sig)
{
    int result;

    result = setjmp(my_jump_buffer, sig);
    printf ("setjmp(): resutl %d \r\n", result);
    if (sig==result)
        return true;
    return false;
}

void signal_handler (int sig)
{
    printf ("signal_handler(%d) \r\n", sig);
    longjmp (g_my_jump_buffer, sig);
}

int main (void)
{
    unsigned int* p = (unsigned int*)0xffffffff;

    signal (SIGBUS, signal_handler);

    while (1)
    {    
        if (try_signal (SIGBUS)==0)
        {
            printf ("no signal \r\n");
            *p = 0x00000001;
        }
        else
        {
            printf ("signal \r\n");
        }
    }
    return 0;
}

Posted by 셈말짓기 :