There are a lot of timeouts in php.ini and php-fpm.conf, but what exactly do they do? How are they implemented in the source code? This article will talk about the following timeout configurations:

php.ini
  • max_execution_time
  • max_input_time
php-fpm.conf
  • process_control_timeout
  • request_terminate_timeout
  • request_slowlog_timeout

Configuration resolution rules

Parsing rules

The parsing of php.ini is done in the php_module_startup() phase. ini_entry is a parsing rule defined in main.c for each php.ini configuration, in the following format:

1

ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, arg3, displayer)

PHP defines many macros for different types of configurations, and ZEND_INI_ENTRY3_EX is the final macro after they are expanded, such as the PHP_INI_ENTRY macro

1

PHP_INI_ENTRY(name, default_value, modifiable, on_modify)

Parameter explanation

name: Placement Name

default_value: Configure default values

modifiable: The configurable range of the configuration can be set

These modes determine when, where and if a PHP directive can be set. Each directive in the manual has a pattern to which it belongs. For example, some directives can be set in PHP scripts with ini_set(), while others can only be set in php.ini or httpd.conf.

For example, the output_buffering directive is part of PHP_INI_PERDIR and therefore cannot be set with ini_set(). The display_errors directive, however, belongs to PHP_INI_ALL and can be set anywhere, including ini_set().

Mode Meaning
PHP_INI_USER Can be set in user scripts (e.g. ini_set()) or in the Windows registry (since PHP 5.3) and in .user.ini
PHP_INI_PERDIR can be set in php.ini, .htaccess or httpd.conf
PHP_INI_SYSTEM can be set in php.ini or httpd.conf
PHP_INI_ALL Can be set anywhere

on_modify: Configuration modification function

max_input_time、max_execution_time

Since max_input_time and max_execution_time are closely related, they are discussed together.

php.ini explained

max_input_time

; Maximum amount of time each script may spend parsing request data. It's a good
; idea to limit this time on productions servers in order to eliminate unexpectedly
; long running scripts.
; Note: This directive is hardcoded to -1 for the CLI SAPI
; http://php.net/max-input-time

 

max_execution_time

; Maximum execution time of each script, in seconds
; http://php.net/max-execution-...
; Note: This directive is hardcoded to 0 for the CLI SAPI

 

Configuration resolution rules

1

2

3

4

5

// max_input_time,Default value is no limit

STD_PHP_INI_ENTRY("max_input_time", "-1",    PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, max_input_time, php_core_globals, core_globals)

   

// max_execution_time,The default value is 30s, modify the function to OnUpdateTimeout

PHP_INI_ENTRY("max_execution_time", "30",    PHP_INI_ALL, OnUpdateTimeout)

The OnUpdateTimeout() function is as follows. As you can see from section 2, the configuration resolution occurs during the php_module_startup() phase, when EG(timeout_seconds) is assigned to max_execution_time, but the timer is not yet set.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// main.c

static PHP_INI_MH(OnUpdateTimeout)

{

    if (stage==PHP_INI_STAGE_STARTUP) {

        /* Don't set a timeout on startup, only per-request */

    /* EG(timeout_seconds) = max_execution_time */

        ZEND_ATOL(EG(timeout_seconds), ZSTR_VAL(new_value));

        return SUCCESS;

    }

    zend_unset_timeout();

    ZEND_ATOL(EG(timeout_seconds), ZSTR_VAL(new_value));

    zend_set_timeout(EG(timeout_seconds), 0);

    return SUCCESS;

}

Set the timeout timer

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

// main.c

int php_request_startup(void)

{

  ......

  if (PG(max_input_time) == -1) {

    zend_set_timeout(EG(timeout_seconds), 1);

  } else {

  zend_set_timeout(PG(max_input_time), 1);

  }

  ......

}

 

int php_execute_script(zend_file_handle *primary_file)

{

  ......

    if (PG(max_input_time) != -1) {

    zend_set_timeout(INI_INT("max_execution_time"), 0);

  

  ......

}

As you can see from the above code, if max_input_time is set (i.e. the value is not equal to -1, -1 can be considered in CLI mode), a timer will be set in the php_request_startup() phase with a timeout of max_input_time; in the php_execute_script() phase Then the maximum execution time of the entire PHP script is equal to max_input_time + max_execution_time.

If max_input_time is not set (i.e. the value is equal to -1), a timer is also set in the php_request_startup() phase, but the timeout time is set to EG(timeout_seconds), which is already set in the php_module_ startup() stage is assigned to max_execution_time, so the timeout time is max_execution_time; the timer is not reset in the php_execute_script() stage, and the max_execution_time timer set in the previous stage is still in effect. . Then the maximum execution time of the entire PHP script is max_execution_time.

zend_set_time() uses setitimer(ITIMER_PROF, &t_r, NULL); to implement the timer. ITIMER_PROF will count the time spent in both user state and kernel state, while system calls like sleep() will let the process hang and not take up cpu time slice, so these two timeouts are not include the sleep() time.

When the timer is up, ZendVM will throw an E_ERROR, or Fatal error error.

process_control_timeout

Explanation of php-fpm.conf

; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds

 

When the master process receives SIGINT, SIGTERM, SIGQUIT, SIGUSR2 signals, it will call fpm_pctl() to process them.

First the master process will decide whether to send SIGQUIT or SIGTERM signals to the worker process based on the received signals and the current running status of fpm, and register a timed event with process_control_timeout.

If the child process does not exit within process_control_timeout time, then the master process will upgrade SIGQUIT to SIGTERM, SIGTERM to SIGKILL, and register a 1s timing event. SIGKILL will directly terminate the worker process, and SIGTERM will give the worker process another 1s. The SIGTERM can give the worker process another 1s of time.

In summary, process_control_timeout can be interpreted as the master process to leave the worker process to end their own time, if the time worker is not done then start the master's own strategy.

request_terminate_timeout、request_slowlog_timeout

Since request_terminate_timeout and request_slowlog_timeout are closely related, they are discussed together.

Explanation of php-fpm.conf

request_terminate_timeout

; The timeout for serving a single request after which the worker process will
; be killed. This option should be used when the 'max_execution_time' ini option
; does not stop script execution for some reason. A value of '0' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0

 

request_slowlog_timeout

; The timeout for serving a single request after which a PHP backtrace will be
; dumped to the 'slowlog' file. A value of '0s' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0

 

Analysis

request_slowlog_timeout and request_terminate_timeout are used in the heartbeat detection of the master process (fpm_pctl_heartbeat()), and the simplified algorithm for heartbeat time heartbeat is

  • With request_terminate_timeout enabled:request_terminate_timeout/1000*3

  • Without request_terminate_timeout enabled:request_slowlog_timeout/1000*3 or 0

  • request_terminate_timeout >= request_slowlog_timeout

The third rule is to ensure that slowlog does not affect normal requests, heartbeat takes 1/3 of the timeout time should be to avoid heartbeat detection too often, because each heartbeat detection needs to traverse all worker processes.

If a timeout event occurs, then the worker process will be directly killed, kill(child_pid, SIGTERM);, after which the kernel recovers resources to close the client_socket and nginx returns 502 errors to the browser.

Related articles

How to configure php.ini to optimize PHP performance?

PHP used in production environment needs to be optimized to make PHP itself perform better, besides writing good PHP code, we also need to configure php.ini. below we will explain the configuration tuning of php.ini from the aspects of memory, file upload

Six design patterns commonly used in PHP

Singleton mode private static variables (to store instances), private constructor methods (to prevent creation of instances), private clone methods (to prevent cloning of objects), public static methods (to provide instances to the outside world)

16 PHP magic methods

In PHP, methods named starting with a double underscore (__) are called magic methods in PHP, and they play a very important role in PHP. Magic methods include

How to split a string into an array in php

In php, you can use the str_split() function to split a string into an array, which splits the string into several substrings of the desired length and combines them into an array; syntax "str_split(string,length)".

php crop image steps

php crop image steps: 1, create a PHP sample file; 2, use "function imageCropper(){...}" method to achieve the image does not change the cropping; 3, through the "function imageZoom (){...}" method to achieve proportional cropping of the image.

How to replace alt with php regular?

php regular to achieve the replacement alt method: 1, create a PHP sample file; 2, get the content to be replaced; 3, through "<img.*?src=[\"|\'](. *?) [\"|\']. *? >" can be replaced by the regular implementation.

How to convert svg to svg in php?

php svg to jpg method: 1, create a PHP sample file; 2, by "public function svgtojpg(){$image =...}" method to achieve the conversion.

Two basic output methods for php

The two basic output methods of php are "echo" and "print". echo is used to output one or more strings, which can take multiple arguments and have no return value, with the syntax "echo($ str)"; and print is used to output a string that can only take one

How to display a mess of php images?

php image display a mess of solutions: 1, open the corresponding PHP code file; 2, in the page header plus "header ("Content-Type: image/jpg");" code to declare the image type can be.

php can't load js css

php can not load js css solution: 1, check the correct path to load; 2, prohibit the use of absolute path; 3, use relative path to load the file can be.