Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible for a program to capture SIGTERM generated by the exit system call?

Tags:

c

signals

The program I have is as follows:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>

int main()
{
    struct sigaction new_sa;
    struct sigaction old_sa;
    sigfillset(&new_sa.sa_mask);
    new_sa.sa_handler = SIG_IGN;
    new_sa.sa_flags = 0;
    int input;

    if (sigaction(SIGTERM, &new_sa, &old_sa) == 0 && old_sa.sa_handler != SIG_IGN) {
        new_sa.sa_handler = NULL;
        sigaction(SIGTERM, &new_sa, 0);
    }

    printf("Pgm is running\n");
    while (1) {
        printf("Enter input\n");
        scanf("%d", &input);
        if (!input) {
            /* I actually call a libraries API which calls exit()
             * Just calling exit here for simpilicity */
            exit(1);
        }
    }
}

I want to handle/ignore SIGTERM generated by exit system call. Is it possible? There is no way for me to avoid calling exit since its actually a library call which is trying to exit the program which i want to avoid.

like image 636
Nikhil Avatar asked Sep 27 '22 02:09

Nikhil


2 Answers

You can certainly catch SIGTERM. But that's not the problem here. You want to override the exit() call.

This is not possible in any portable or standard compliant way. The exit() is one of the functions that's defined to not return to its caller. Typically, this is done using the __attribute__((noreturn)) in gcc and C11 has introduced the macro _Noreturn for the same purpose.

Attempting to return from such function, like exit(), is undefined behaviour.

There are few options, I can think of:

  • Compile and replace with your function: gcc -Dexit=not_exit file.c
  • Write a hook function for exit(). See here for an example. Implementing a hook function may not work at all since this noreturn has existed on most libc implementations before C11's _Noreturn.
  • Use GNU's ld as suggested by @evading. I believe this equivalent to the above but the linker does half of the work for you.

Modifying <stdlib.h> to remove the _Noreturn (or its equivalent) attribute for the exit() function might make it work. None of these is guaranteed to work. We are already well into the UB land.

Other option is to an install atexit() handler, which might be useful if you want to do something before exit().

A saner approach would be to modify the library if you to not call exit() but instead return a error code. In my opinion, either the library is badly designed that it randomly exits on its own or probably there's a good reason that the library exits (due to some unrecoverable error) and your application is not supposed to continue any further, which you are attempting to do.

like image 79
P.P Avatar answered Sep 30 '22 07:09

P.P


Looking at the glibc source for exit it looks like it isn't possible. But it might be if you're using another C std library.

You can do stuff at_exit but you can't prevent it.

[edit]

Everything below here is apparently not applicable for exit for the reasons in this question.

If you use gnu ld it might be possible to override __run_exit_handlers, or exit for that matter, using the gnu ld --wrap option but I havn't tried it.

If you can use gnu ld you could do --wrap exit and then implement __wrap_exit() in your code. If you want to call exit after this you can access it through __real_exit(). This is a gnu ld feature and I'm not sure how universally available it is.

like image 36
evading Avatar answered Sep 30 '22 07:09

evading