Search code examples
phpsignalspcntl

php signal not handled right away


I have a software written in PHP which can run for a long time, it's lauched via command line (not a web application). I wanted to make sure to call a function when the software exit, including when killed via ctrl+c. When killed by a signal, the shutdown functions (destructors and functions registered via register_shutdown_fucntion() ) are not called.

After some reading, I realized I had to add a handler on every relevant signal just to call "exit;". Doing so solved my problem and works.

My issue is that in some case, the signal is not handled right away. It can take seconds, minutes and in some case, is not handled at all. Just like if the handler code was never reached. I don't really know where to start to debug that. I've tried others signals (sigkill, sighup, etc), same behaviour.

My code is withing these brackets

declare(ticks=1)
{...}

I can't find any correlation between the time it get treated right away and the ones that it doesn't.

Any help would be appreciated.


Solution

  • The signal should be handled this way : First, you have to make a signal handler like this :

    function signalHandler($signo = null) {
        $pid = posix_getpid();
        switch ($signo) {
            //case SIGKILL: // you can't override SIGKILL so it is useless
            case SIGTERM:
            case SIGINT:
                // unexpected shut down
                exit(3);
                break;
            case SIGCHLD:
            case SIGHUP:
                // just ignore it
                break;
            case 10:
                // user signal 1 received. Process exited normally
                exit(0);
                break;
            case 12:
                // user signal 2 received. Precess exited with a catched error
                exit(3);
                break;
            default:
                // ignore other signals
        }
    }
    

    then, in your main process, you have to tell PCNTL you are using this handler :

        pcntl_signal(SIGTERM, "signalHandler");
        pcntl_signal(SIGINT, "signalHandler");
    //  pcntl_signal(SIGKILL, "signalHandler"); // you can't override SIGKILL so it is useless
        pcntl_signal(SIGCHLD, "signalHandler");
        pcntl_signal(SIGHUP, "signalHandler");
        pcntl_signal(10, "signalHandler");
        pcntl_signal(12, "signalHandler");
    

    I'm using this and seems to work for 200 process, 8 process running at the same time, and 10 sec for each process.

    Here, when a process exits, he sends a signal 10 or 12 (for success or error) using posix_kill($pid, 10)