Search code examples
clinuxsigaction

sigaction and ignoring a signal with c in linux environment


I am new to this type of programming, so sorry if my question is trivial. What I am trying to do is to cause a segmentation fault in my program and instead of exiting the program, I want to handle the signal and continue execution after segmentation fault. I wrote a code that seem to be working, I just want to make sure that this is the way to do this. So here is my code.

void myhandle(int mysignal, siginfo_t *si, void* arg)
{
  printf("Signal is %d\n",mysignal);

  ucontext_t *context = (ucontext_t *)arg;
  context->uc_mcontext.gregs[REG_RIP]++;
}


int main(int argc, char *argv[])
{
   struct sigaction action;

  action.sa_handler=myhandle;
  sigaction(11,&action,NULL);

  printf("Before segfault\n");

  int *a=NULL;
  int b=*a;

  printf("I am still alive\n");

  return 0;
}

Can someone explain to me why the printf inside myhandle runs twice ? Also is this code ok ?

Thank you.


Solution

  • By this example i have modified your code at below way and now it works as you wanted.

    #include<stdio.h>
    #define __USE_GNU
    #include<signal.h>
    #include<ucontext.h>
    
    void myhandle(int mysignal, siginfo_t *si, void* arg)
    {
      printf("Signal is %d\n",mysignal);
    
      ucontext_t *context = (ucontext_t *)arg;
      context->uc_mcontext.gregs[REG_RIP] = context->uc_mcontext.gregs[REG_RIP] + 0x04 ;
    }
    
    
    int main(int argc, char *argv[])
    {
    
      struct sigaction action;
      action.sa_sigaction = &myhandle;
      action.sa_flags = SA_SIGINFO;
    
      sigaction(11,&action,NULL);
    
    
      printf("Before segfault\n");
    
      int *a=NULL;
      int b;
      b =*a;
    
      printf("I am still alive\n");
    
      return 0;
    }
    

    Output:

    jeegar@jeegar:~/stackoverflow$ gcc test1.c
    jeegar@jeegar:~/stackoverflow$ ./a.out 
    Before segfault
    Signal is 11
    I am still alive
    

    On further question form OP in commentes. To runtime remove this handler for this signel

    void myhandle(int mysignal, siginfo_t *si, void* arg)
    {
      printf("Signal is %d\n",mysignal);
    
    if(flag == 0) {
      // Disable the handler
      action.sa_sigaction = SIG_DFL;
      sigaction(11,&action,NULL);
    }
    
    if(flag) {
      ucontext_t *context = (ucontext_t *)arg;
      context->uc_mcontext.gregs[REG_RIP] = context-      >uc_mcontext.gregs[REG_RIP] + 0x04 ;
    }
    
    }