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

I have the following program:

#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 the SIGTERM generated by the exit system call. Is it possible? I will not be able to avoid the exit call, since it is actually a library call that is trying to exit the program I want to avoid.

+5
source share
3 answers

Looking at the glibc source for the output, it seems like this is not possible. But maybe if you use another C. std library.

You can do at_exit things, but you cannot prevent this.

[edit]

Everything below here, apparently, is not applicable to exit for reasons from this issue .

If you are using gnu ld, you can __run_exit_handlers override __run_exit_handlers or exit using the gnu ld --wrap , but I have not tried it.

If you can use gnu ld, you can do --wrap exit , and then implement __wrap_exit() in your code. If you want to call exit after this, you can access it via __real_exit() . This is the gnu ld function, and I'm not sure how accessible it is.

+2
source

You can surely catch SIGTERM . But it's not a problem. You want to override the exit() call.

This is not possible in any portable or standard agreement. exit() is one of the functions that do not return to the caller. This is usually done using __attribute__((noreturn)) in gcc, and C11 introduces the _Noreturn macro for the same purpose.

Trying to return from such a function, for example exit() , undefined behavior .

There are several options that I can think of:

  • Compile and replace your function: gcc -Dexit=not_exit file.c
  • Write a hook function for exit() . See here for an example. An implementation of the hook function may not work at all, since this noreturn exists in most libc implementations prior to C11 _Noreturn .
  • Use GNU ld, as suggested by @evading. I believe this is equivalent to the above, but the linker does half the work for you.

Changing <stdlib.h> to remove the _Noreturn attribute (or its equivalent) for the exit() function may make it work. None of them are guaranteed to work. We are already well entering the land of UB.

Another option is the install atexit() handler, which can be useful if you want to do something before exit() .

A more robust approach would be to change the library if you do not call exit() , but instead return an error code. In my opinion, either the library is poorly designed that it accidentally exits by itself, or there is probably a good reason why the library exits (due to some fatal error), and your application should not continue further, what are you trying to do .

+2
source

Ability to start a library call in a child process using fork . This does not stop calling exit , but it can be a workaround if you want to handle this error yourself.

Following the Fork, Exec, and Process Management manual. I use channels to send the result of a library call if the call is successful.

 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main(){ int pipefd[2]; pipe(pipefd); //Create pipe for communication pid_t pid = fork(); if (pid == 0){ //Child process close(pipefd[0]); // close the read-end of the pipe, printf("Run library here\n"); // exit(3); if failed int val=4; //Result of library call send to parent write(pipefd[1], &val, sizeof(val)); close(pipefd[1]); // close the write-end of the pipe exit(EXIT_SUCCESS); } else if (pid < 0){ printf("Failed to fork\n"); } else{//Parent process close(pipefd[1]); printf("Parent process\n"); int status=0; int pid=wait(&status); printf("The pid %d finished with status %d\n",pid,status); if (status==EXIT_SUCCESS){//The library call was successful int val=2; read(pipefd[0],&val,sizeof(int)); //Read data from pipe and do something with it printf("Value %d received\n",val); } close(pipefd[0]); } return 0; } 
0
source

Source: https://habr.com/ru/post/1236892/


All Articles