Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abort function in C

Tags:

c

linux

unix

abort

Program 1:

#include<stdio.h>
#include<signal.h>
void handler(int sig);
void main()
{
    printf("PID: %d\n",getpid());
    signal(SIGABRT,handler);
    while(1){
        printf("Hai\n");
        sleep(1);
        abort();
    }
}

void handler(int sig)
{
    printf("Signal handled\n");
}

Output 1:

$ ./a.out 
PID: 32235
Hai
Signal handled
Aborted (core dumped)
$

As per the reference, the abort function works like raise(SIGABRT). So, the signal generated by abort() function is SIGABRT. So for that I created the above program.

In that program, SIGABRT signal is handled. After the execution of signal handler, it doesn't return to the main function from where it is called. Why does it not return to the main function after the handler is completed?

Program 2:

#include<stdio.h>
#include<signal.h>
void handler(int sig);
void main()
{
    printf("PID: %d\n",getpid());
    signal(SIGABRT,handler);
    while(1){
        printf("Hai\n");
        sleep(1);
    }
}

void handler(int sig)
{
    printf("Signal handled\n");
}

Output 2:

$ ./a.out 
PID: 32247
Hai
Hai
Hai
Signal handled
Hai
Signal handled
Hai
Hai
^C
$ 

Unlike program 1, program 2 executes as expected. In the above program, the signals are sent to the process via command line through the kill command as shown below.

$ kill -6 32247
$ kill -6 32247

So once the signal occurred, the handler function executed and then it returns to the main function. But it does not happen in program 1. Why does it behave like this? The abort function and SIGABRT are different?

like image 596
mohangraj Avatar asked Nov 06 '15 11:11

mohangraj


People also ask

What is abort () in C?

In the C Programming Language, the abort function raises the SIGABRT signal, and causes abnormal program termination that returns an implementation defined code indicating unsuccessful termination.

What is use of abort function?

The abort function causes abnormal program termination. This does not execute cleanup functions registered with atexit or on_exit . This function actually terminates the process by raising a SIGABRT signal, and your program can include a handler to intercept this signal; see Signal Handling.

What is exit abort?

abort sends a SIGABRT signal, exit just closes the application performing normal cleanup. You can handle an abort signal however you want, but the default behavior is to close the application as well with an error code. abort will not perform object destruction of your static and global members, but exit will.

What happens on exit ()?

On many computer operating systems, a computer process terminates its execution by making an exit system call. More generally, an exit in a multithreading environment means that a thread of execution has stopped running. For resource management, the operating system reclaims resources (memory, files, etc.)


2 Answers

See this piece of documentation from man 3 abort:

This results in the abnormal termination of the process unless the SIGABRT signal is caught and the signal handler does not return (see longjmp(3)).

And also this:

If the SIGABRT signal is ignored, or caught by a handler that returns, the abort() function will still terminate the process. It does this by restoring the default disposition for SIGABRT and then raising the signal for a second time.

So the only way you can prevent abort() from aborting your program is by longjmp()-ing from the signal handler.

like image 66
rodrigo Avatar answered Sep 23 '22 12:09

rodrigo


Libc implements abort(). In their implementation, abort() checks to see if the process is still alive, because abort() is executing after the raise(SIGABRT). If it is, then it knows that the user has handled SIGABRT. According to the documentation, it doesn't matter, because the process will still exit:

You can see the exact implementation in the GLIBC source code (stdlib/abort.c):

/* Cause an abnormal program termination with core-dump.  */
void
abort (void)
{
  struct sigaction act;
  sigset_t sigs;

  /* First acquire the lock.  */
  __libc_lock_lock_recursive (lock);

  /* Now it's for sure we are alone.  But recursive calls are possible.  */

  /* Unlock SIGABRT.  */
  if (stage == 0)
    {
      ++stage;
      if (__sigemptyset (&sigs) == 0 &&
      __sigaddset (&sigs, SIGABRT) == 0)
    __sigprocmask (SIG_UNBLOCK, &sigs, (sigset_t *) NULL);
    }

  /* Flush all streams.  We cannot close them now because the user
     might have registered a handler for SIGABRT.  */
  if (stage == 1)
    {
      ++stage;
      fflush (NULL);
    }

  /* Send signal which possibly calls a user handler.  */
  if (stage == 2)
    {
      /* This stage is special: we must allow repeated calls of
     `abort' when a user defined handler for SIGABRT is installed.
     This is risky since the `raise' implementation might also
     fail but I don't see another possibility.  */
      int save_stage = stage;

      stage = 0;
      __libc_lock_unlock_recursive (lock);

      raise (SIGABRT);

      __libc_lock_lock_recursive (lock);
      stage = save_stage + 1;
    }

  /* There was a handler installed.  Now remove it.  */
  if (stage == 3)
    {
      ++stage;
      memset (&act, '\0', sizeof (struct sigaction));
      act.sa_handler = SIG_DFL;
      __sigfillset (&act.sa_mask);
      act.sa_flags = 0;
      __sigaction (SIGABRT, &act, NULL);
    }

  /* Now close the streams which also flushes the output the user
     defined handler might has produced.  */
  if (stage == 4)
    {
      ++stage;
      __fcloseall ();
    }

  /* Try again.  */
  if (stage == 5)
    {
      ++stage;
      raise (SIGABRT);
    }

  /* Now try to abort using the system specific command.  */
  if (stage == 6)
    {
      ++stage;
      ABORT_INSTRUCTION;
    }

  /* If we can't signal ourselves and the abort instruction failed, exit.  */
  if (stage == 7)
    {
      ++stage;
      _exit (127);
    }

  /* If even this fails try to use the provided instruction to crash
     or otherwise make sure we never return.  */
  while (1)
    /* Try for ever and ever.  */
    ABORT_INSTRUCTION;
}
like image 35
Jonathon Reinhart Avatar answered Sep 23 '22 12:09

Jonathon Reinhart