Vermeidung eines data races mit signal handlern



  • Hallöchen,
    ich wollte mal fragen, ob jemandem eine bessere Herangehensweise zu dem Code hier einfällt:

    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <stdbool.h>
    
    #include <sys/epoll.h>
    
    static sig_atomic_t volatile running = true;
    
    static void signal_handler(int sig)
    {
    	(void)sig;
    
    	running = false;
    }
    
    int main(void)
    {
    	struct sigaction sa = { .sa_handler = &signal_handler };
    	sigemptyset(&sa.sa_mask);
    	sigaction(SIGINT, &sa, 0);
    	sigaction(SIGTERM, &sa, 0);
    
    	sigset_t sigmask;
    	sigemptyset(&sigmask);
    	sigaddset(&sigmask, SIGINT);
    	sigaddset(&sigmask, SIGTERM);
    
    	int epollfd;
    	// ... init stuff ...
    	
    	while (running)
    	{
    		sigset_t oldmask;
    		sigprocmask(SIG_BLOCK, &sigmask, &oldmask);
    
    		if (!running)
    		{
    			sigprocmask(SIG_SETMASK, &oldmask, 0);
    			break;
    		}
    
    		struct epoll_event event;
    		int ret = epoll_pwait(epollfd, &event, 1, -1, &oldmask);
    		int err = errno;
    		sigprocmask(SIG_SETMASK, &oldmask, 0);
    		if (ret == -1 && err == EINTR)
    			continue;
    
    		// ... do stuff ...
    	}
    
    	// ... cleanup stuff ...
    }
    

    Irgendwie sieht mir dieses hin und her mit dem sigprocmask sehr umständlich aus um die race condition zu vermeiden, die entsteht, wenn man es so macht:

    while (running)
    {
    	// Wenn hier das Signal kommt, blockiert epoll für immer.
    
    	struct epoll_event event;
    	int ret = epoll_wait(epollfd, &event, 1, -1);
    }
    

    Fällt jemandem was besseres ein, oder ist das so in Ordnung?


Log in to reply