What is the “good” setting for PHP ticks using pcntl_signal?

I run the PHP daemon with a signal handler for orderly cleaning and for reconfiguring without stopping:

declare(ticks = 5); function sig_handler($signo) { ... } pcntl_signal(SIGHUP, 'sig_handler'); pcntl_signal(SIGINT, 'sig_handler'); ... 

A chip is an event that occurs for every N low-level ticking statements executed by the parser in the declare block ... Not all statements are tickable. As a rule, condition expressions and argument expressions are not tick.

If we declare ticks = 1 , then the signal between most lines of PHP code will be checked, which seems inefficient. In this way,

  • If we declare ticks = 5 , does this mean that we have a 4 in 5 probability that the signal handler will not be called at all?
  • How to determine consistent but effective tuning?
  • What happens when blocking calls, such as database queries? Is a signal called or processed when it returns?

(Lateral note: Formal specifications are even less specific, as this probably depends on the interpreter.)

+5
source share
1 answer

The following are my findings, I can’t provide you with any link to the documentation supporting my statements. However, I found out how the PHP interpreter processes ticks and signals by reading the PHP source code ( pcntl extension).

  • If we set ticks = 5 , does this mean that we have a probability of 4 in 5, the signal handler will not be called at all?

PHP is an interpreted language. The OS processes your PHP signal handlers to process the signals. The interpreter registers a signal processor from the OS and puts all the signals that it receives into the queue.

OS signals arrive asynchronously. The interpreter sends signals to the handlers you define when it is the most suitable time for it. This occurs between low-level ticking statements.

declare(ticks = 5); forces the signal manager to run every 5 ticks. Signals received during two calls to the dispatcher are not lost; they are added to the queue and processed on the next call.

The signal manager code is pretty light; there is no big overhead to use declare(ticks = 1) .

  • How to determine consistent but effective tuning?

It depends on what your program does. There is no recipe for this. Try different settings, choose the one that suits you.

  • What happens when blocking calls, such as database queries? Is a signal called or processed when it returns?

As I said before, signals are received and processed asynchronously by the signal handler installed by the interpreter. Processing only queues the signals. They are selected from the queue and sent to your code when it is the best time for the interpreter (and your PHP code too). Nothing is lost.

As for the database, I only checked (a few years ago) with mysql . My code used pcntl_fork() to create workflows and processed SIGCHLD to track worker activity. For mysterious reasons, he often failed in MySQL queries with the message “lost connection” for no apparent reason. After extensive research and reading a lot of documentation, I found out that signals perform functions from sleep() returning the family earlier, and this makes the client library code mysql believes that the connection was lost.

The solution was very simple. I used pcntl_sigprocmask() to block the SIGCHLD signal before starting the MySQL query and unlock it immediately after the query is complete. I was not interested in other signals. Allowing them to terminate the process; why bother with a failed MySQL query when the program was about to exit anyway?

I don’t know if signals affect mysqli or PDO , but I think they do. The operation that was affected in my case was part of the low-level communication between the client and the MySQL server, deep in libmysql and not in the PHP extension.

In your case, you probably need to block SIGHUP (this is a signal that is usually sent to daemons to overload their configuration).

+5
source

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


All Articles