{@inheritdoc}

@throws \AsyncInterop\Loop\UnsupportedFeatureException If the pcntl extension is not available.
@throws \RuntimeException If creating the backend signal handler fails.
325514
public function onSignal($signo, callable $callback, $data = null) {
        $watcher = new Watcher;
        $watcher->type = Watcher::SIGNAL;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $signo;
        $watcher->data = $data;

        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;

        return $watcher->id;
    }
611363
public static function handleCommand() {
        try {
            global $argv;
            $tokens = array_slice($argv, 1);

            if (empty($tokens)) {
                throw new RuntimeException("Command name is required !!");
            }

            $commandName = (string)$tokens[0];
            $commandTokens = array_slice($tokens, 1);

            $commandParameters = [];
            $currentCommandName = null;

            for ($i = 0; $i < sizeof($commandTokens); $i++) {
                $commandToken = $commandTokens[$i];

                if (substr($commandToken, 0, 2) == '--') {
                    if ($currentCommandName != null) {
                        $commandParameters[$currentCommandName] = true;
                    }
                    $currentCommandName = substr($commandToken, 2);
                }
                else {
                    if ($currentCommandName == null) {
                        throw new RuntimeException("Invalid argument \"$commandToken\". Arguments must start with \"--\"");
                    }
                    $commandParameters[$currentCommandName] = $commandToken;
                    $currentCommandName = null;
                }
            }

            if ($currentCommandName != null) {
                $commandParameters[$currentCommandName] = true;
            }

            self::executeCommand($commandName, $commandParameters);
        }
        catch (CommandNotFoundException $exception) {
            get_logger()->warning($exception->getMessage());
            echo $exception->getMessage() . "\n";
        }
    }
720901
public function signalReceived($signal)
	{
		if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) {
			$class = get_class($this);
			throw new BadSignalException("There is no handler for signal '$signal' in class $class.");
		}
	}
376645
public static function isSupported()
    {
        if (null === self::$supported) {
            self::$supported = function_exists('cli_set_process_title') || function_exists('setproctitle');
        }

        return self::$supported;
    }
256253
public function get(string $signal): callable
    {
        return $this->handlers[$signal] ?? static function () use ($signal) {
            throw new Exception\UnknownSignal($signal);
        };
    }
632514
public function childSignalHandler( $signo, $pid = null, $status = null )
    {
        // If no pid is provided, that means we're getting the signal from the system.  Let's figure out
        // which child process ended
        if( $pid === null )
        {
            $pid = pcntl_waitpid( -1, $status, WNOHANG );
        }

        //Make sure we get all of the exited children
        while( $pid > 0 )
        {
            if( $pid && isset( $this->currentJobs[$pid] ) )
            {
                $exitCode = pcntl_wexitstatus( $status );
                if ( $exitCode != 0 )
                {
                    $this->out->write( "Process #{$pid} of object version #".$this->currentJobs[$pid]->attribute( 'ezcontentobject_version_id' ) . " exited with status {$exitCode}" );
                    // this is required as the MySQL connection might be closed anytime by a fork
                    // this method is asynchronous, and might be triggered by any signal
                    // the only way is to use a dedicated DB connection, and close it afterwards
                    eZDB::setInstance( eZDB::instance( false, false, true ) );

                    $this->currentJobs[$pid]->reset();

                    eZDB::instance()->close();
                    eZDB::setInstance( null );
                }
                unset( $this->currentJobs[$pid] );
            }
            // A job has finished before the parent process could even note that it had been launched
            // Let's make note of it and handle it when the parent process is ready for it
            // echo "..... Adding $pid to the signal queue ..... \n";
            elseif( $pid )
            {
                $this->signalQueue[$pid] = $status;
            }
            $pid = pcntl_waitpid( -1, $status, WNOHANG );
        }
        return true;
    }
842993
public function signal_handler_sigchild($signal_number)
	{
		// do not allow signals to interrupt this
		pcntl_async_signals(false);
		{
			// reap all child zombie processes
			if (self::$parent_pid == getmypid())
			{
				$status = '';

				do
				{
					// get child pid that exited
					$child_pid = pcntl_waitpid(0, $status, WNOHANG);
					if ($child_pid > 0)
					{
						// child exited
						$identifier = false;
						if (!isset($this->forked_children[$child_pid]))
						{
							$this->log("Cannot find $child_pid in array! (This may be a subprocess not in our fork)", self::LOG_LEVEL_INFO);
							continue;
						}

						$child = $this->forked_children[$child_pid];
						$identifier = $child['identifier'];

						// call exit function if and only if its declared */
						if ($child['status'] == self::WORKER)
						{
							$this->invoke_callback($this->parent_function_child_exited[ $this->forked_children[$child_pid]['bucket'] ], array($child_pid, $this->forked_children[$child_pid]['identifier']), true);
						}

						// stop the child pid
						$this->forked_children[$child_pid]['status'] = self::STOPPED;
						$this->forked_children_count--;

						// respawn helper processes
						if ($child['status'] == self::HELPER && $child['respawn'] === true)
						{
							$this->log('Helper process ' . $child_pid . ' died, respawning', self::LOG_LEVEL_INFO);
							$this->helper_process_spawn($child['function'], $child['arguments'], $child['identifier'], true);
						}

						// Poll for results from any children
						$this->post_results($child['bucket']);
					}
					elseif ($child_pid < 0)
					{
						// ignore acceptable error 'No child processes' given we force this signal to run potentially when no children exist
						if (pcntl_get_last_error() == 10)
						{
							continue;
						}

						// pcntl_wait got an error
						$this->log('pcntl_waitpid failed with error ' . pcntl_get_last_error() . ':' . pcntl_strerror((pcntl_get_last_error())), self::LOG_LEVEL_DEBUG);
					}
				} while ($child_pid > 0);
			}
		}
	}
1069362
public function signal($signal)
    {
        // Log all signals sent to the daemon.
        $this->getLogger()->debug('Received signal: ' . $signal);

        // Let's make sure we have an application instance.
        if (!is_subclass_of($this, __CLASS__)) {
            $this->getLogger()->emergency('Cannot find the application instance.');

            throw new \RuntimeException('Cannot find the application instance.');
        }

        // @event onReceiveSignal

        switch ($signal) {
            case SIGINT:
            case SIGTERM:
                // Handle shutdown tasks
                if ($this->running && $this->isActive()) {
                    $this->shutdown();
                } else {
                    $this->close();
                }

                break;

            case SIGHUP:
                // Handle restart tasks
                if ($this->running && $this->isActive()) {
                    $this->shutdown(true);
                } else {
                    $this->close();
                }

                break;

            case SIGCHLD:
                // A child process has died
                while ($this->pcntlWait($signal, WNOHANG || WUNTRACED) > 0) {
                    usleep(1000);
                }

                break;

            case SIGCLD:
                while ($this->pcntlWait($signal, WNOHANG) > 0) {
                    $signal = $this->pcntlChildExitStatus($signal);
                }

                break;

            default:
                break;
        }
    }
915516
protected function seedHandlerStack()
    {
        if (!is_null($this->handlers)) {
            throw new \RuntimeException('Handler stacks can only be seeded once.');
        }
        $this->stacks = [];
        $base = new BaseHandler();
        $this->handlers = [$base];

        $this->stacks['delete'] = new \SplStack();
        $this->stacks['clean'] = new \SplStack();
        $this->stacks['create'] = new \SplStack();
        $this->stacks['read'] = new \SplStack();
        $this->stacks['write'] = new \SplStack();

        foreach($this->stacks as $id => $stack) {
            $stack->setIteratorMode(\SplDoublyLinkedList::IT_MODE_LIFO | \SplDoublyLinkedList::IT_MODE_KEEP);
            $stack[] = array( $base, $id );
        }
    }
261384
public function end()
    {
        if (null === $this->ifPart) {
            throw new \RuntimeException('You must specify an if part.');
        }
        if (null === $this->thenPart) {
            throw new \RuntimeException('You must specify a then part.');
        }

        return $this->node;
    }
645165
public function getExitCode()
    {
        if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
        }

        $this->updateStatus(false);

        return $this->exitcode;
    }
464380
public function signalReceived($signal): void
    {
        $form = $this->getForm();
        /** @var Presenter $presenter */
        $presenter = $this->getPresenter();
        $request = $presenter->getRequest();

        switch ($signal) {
            case 'submit':
                $this->processSubmit($form, $request);
                break;
            case 'validate':
                $this->processValidate($form, $request);
                break;
            case 'render':
                $this->processRender($form, $request);
                break;
            default:
                throw new BadSignalException(
                    sprintf('Missing handler for signal "%s" in %s.', $signal, get_class($this))
                );
        }
    }
427250
private function checkCapabilities(ClientInterface $client)
    {
        if ($client->getConnection() instanceof AggregateConnectionInterface) {
            throw new NotSupportedException(
                'Cannot initialize a PUB/SUB consumer over aggregate connections.'
            );
        }

        $commands = array('publish', 'subscribe', 'unsubscribe', 'psubscribe', 'punsubscribe');

        if ($client->getProfile()->supportsCommands($commands) === false) {
            throw new NotSupportedException(
                'The current profile does not support PUB/SUB related commands.'
            );
        }
    }
846634
public function start()
    {
        if (!empty($this->pid) && $this->isRunning()) {
            throw new \LogicException("the process is already running");
        }

        $callback = $this->getCallable();

        $pid = pcntl_fork();
        if ($pid < 0) {
            throw new \RuntimeException("fork error");
        } elseif ($pid > 0) {
            $this->pid = $pid;
            $this->running = true;
            $this->started = true;
        } else {
            $this->pid = getmypid();
            $this->signal();
            foreach ($this->signal_handlers as $signal => $handler) {
                pcntl_signal($signal, $handler);
            }
            call_user_func($callback);
            exit(0);
        }
    }
254048
protected function signalHandler($signo)
    {
        //accept signal once
        if ($this->signo === null) {
            switch ($signo) {
                //terminate
                case SIGTERM:
                case SIGINT:
                    $this->signo = $signo;
                    break;
                //restart
                case SIGHUP:
                    $this->signo = $signo;
                    register_shutdown_function(function () {
                        pcntl_exec($this->fullName[0], array_slice($this->fullName, 1));
                    });
                    break;
                //the others just ignore
                default:
                    break;
            }
        }
    }
1261237
public function execute()
	{
		// @event onBeforeExecute

		// Enable basic garbage collection.
		gc_enable();

		$this->getLogger()->info('Starting ' . $this->name);

		// Set off the process for becoming a daemon.
		if ($this->daemonize())
		{
			// Declare ticks to start signal monitoring. When you declare ticks, PCNTL will monitor
			// incoming signals after each tick and call the relevant signal handler automatically.
			declare (ticks = 1);

			// Start the main execution loop.
			while (true)
			{
				// Perform basic garbage collection.
				$this->gc();

				// Don't completely overload the CPU.
				usleep(1000);

				// Execute the main application logic.
				$this->doExecute();
			}
		}
		else
		// We were not able to daemonize the application so log the failure and die gracefully.
		{
			$this->getLogger()->info('Starting ' . $this->name . ' failed');
		}

		// @event onAfterExecute
	}
465388
public static function fork()
    {
        $pid = pcntl_fork();
        if ($pid === -1) {
            throw new \RuntimeException('Failed to fork PHP process');
        } elseif ($pid > 0) {
            // This is the parent process. If the child process succeeds, this
            // receives SIGCHLD. If it fails, this receives SIGTERM.
            declare (ticks = 1);
            pcntl_signal(SIGCHLD, function () {
                exit;
            });
            pcntl_signal(SIGTERM, function () {
                exit(1);
            });

            // Wait a reasonable amount of time for the child processes to
            // finish.
            sleep(60);
            throw new \RuntimeException('Timeout in parent process');
        } elseif (posix_setsid() === -1) {
            throw new \RuntimeException('Child process failed to become session leader');
        }
    }