How to make a function asynchronous signal safe?

I have the following function sigaction handler

 void signal_term_handler(int sig) { printf("EXIT :TERM signal Received!\n"); int rc = flock(pid_file, LOCK_UN | LOCK_NB); if(rc) { char *piderr = "PID file unlock failed!"; fprintf(stderr, "%s\n", piderr); printf(piderr); } abort(); } 

Someone told me that flock and printf are not safe for an asynchronous signal. And I could not find an alternative security function with an asynchronous signal for flock in this.

and in accordance with the above link:

when a signal interrupts an unsafe function and a signal function calls an unsafe function, the behavior is undefined

Is there any way to make flock asynchronous signal safe? Or is there another solution to execute flock when I receive a TERM signal?

+6
source share
3 answers

You can use fcntl () as an alternative to flock ().

+4
source

flock() is generally safe as a signal since it is a system call. Its semantics makes it difficult to implement it in different ways. It is not in the POSIX list of functions supporting an asynchronous signal, because it is not in POSIX at all.

You probably don't need an explicit unlock, because flock() locks are automatically released when all file descriptors that reference a description of an open file are closed.

The calls to printf() and fprintf() should be replaced by the corresponding calls to write() . The stdio functions are not included in the list of safe functions for asynchronous signals and are often very dangerous for an asynchronous signal.

The abort() call is probably best replaced by setting the signal to the default action and resending it to itself; this way, the shells know that your program has gone out due to a signal and can interrupt command sequences when necessary.

+4
source

You can use exit() instead of abort() in the signal handler, and then put your unsafe functions in the output handler using atexit () .

update: In general, you should not put any potentially blocking system calls in your signal handler. One way to avoid this is to simply set the flag in the signal handler and then perform the necessary functions in the context of the main loop.

 volatile int shutdown = 0; void signal_term_handler(int sig) { shutdown = 1; } void cleanup() { printf("EXIT :TERM signal Received!\n"); int rc = flock(pid_file, LOCK_UN | LOCK_NB); if(rc) { char *piderr = "PID file unlock failed!"; fprintf(stderr, "%s\n", piderr); printf(piderr); } } void *workerFunction(void *arg) { while (!shutdown) { ... do stuff ... } return NULL; } int main(int argc, char *argv[]) { //... pthread_create(...,workerFunction,...); pthread_join(...); cleanup(); return 0; } 
0
source

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


All Articles