diff --git a/NEWS b/NEWS index 44fb719c6982..576a965c4afc 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.7.0alpha1 +- CLI: + . Added the --enable-cli-fpm configure option, which links the FPM SAPI into + the php binary so that "php --fpm" (or a php-fpm symlink to php) runs + php-fpm. (Matthieu Napoli) + - Curl: . curl_multi_exec() now throws a TypeError when still_running is not an int. (arshidkv12) diff --git a/UPGRADING b/UPGRADING index 46cf4cafab12..a761c922894b 100644 --- a/UPGRADING +++ b/UPGRADING @@ -52,6 +52,13 @@ PHP 8.7 UPGRADE NOTES 3. Changes in SAPI modules ======================================== +- CLI: + . When PHP is configured with --enable-cli-fpm, the php binary also contains + the FPM SAPI: "php --fpm [php-fpm options]" behaves like php-fpm. The flag + is only recognized as the first argument. The binary also behaves like + php-fpm when invoked under a name starting with "php-fpm" (e.g. through a + php-fpm symlink). The default build is unchanged. + ======================================== 4. Deprecated Functionality ======================================== diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 2f6ea7d9ea84..032328af21be 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -45,6 +45,7 @@ PHP 8.7 INTERNALS UPGRADE NOTES - The INIT_CLASS_ENTRY_INIT_METHODS() macro, which was previously used as part of handling disabled classes, was removed following the removal of the `disable_classes` INI setting in PHP 8.5. +- Added fpm_main(), the former main() of php-fpm. ======================== 2. Build system changes @@ -57,6 +58,10 @@ PHP 8.7 INTERNALS UPGRADE NOTES - Unix build system changes: . Autoconf minimum required version upgraded to 2.71. + . The --enable-fpm option moved to sapi/fpm/config0.m4 so that other SAPIs + can test $PHP_FPM. The FPM sources other than the main() entry point are + now built into PHP_FPM_SHARED_OBJS. The new --enable-cli-fpm option links + them into the CLI binary. ======================== 3. Module changes diff --git a/sapi/cli/config.m4 b/sapi/cli/config.m4 index 6abaa88df419..26b5b81a250f 100644 --- a/sapi/cli/config.m4 +++ b/sapi/cli/config.m4 @@ -5,6 +5,22 @@ PHP_ARG_ENABLE([cli], [yes], [no]) +PHP_ARG_ENABLE([cli-fpm], + [whether to link FPM into the CLI binary], + [AS_HELP_STRING([--enable-cli-fpm], + [Link the FPM SAPI into the CLI binary, so that "php --fpm" runs php-fpm + (requires --enable-fpm)])], + [no], + [no]) + +if test "$PHP_CLI_FPM" != "no"; then + if test "$PHP_CLI" = "no" || test "$PHP_FPM" = "no"; then + AC_MSG_ERROR([--enable-cli-fpm requires both the CLI and the FPM SAPI]) + fi + AC_DEFINE([PHP_CLI_WITH_FPM], [1], + [Define to 1 if the FPM SAPI is linked into the CLI binary.]) +fi + dnl The embed SAPI requires the CLI sources for do_php_cli(). if test "$PHP_EMBED" != "no" -a "$PHP_CLI" = "no"; then AC_MSG_ERROR([--enable-embed requires the CLI SAPI, do not use --disable-cli with --enable-embed]) @@ -47,6 +63,8 @@ if test "$PHP_CLI" != "no"; then [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1], [PHP_CLI_SHARED_OBJS]) PHP_CLI_OBJS="$PHP_CLI_OBJS $PHP_CLI_SHARED_OBJS" + AS_VAR_IF([PHP_CLI_FPM], [no],, + [PHP_CLI_OBJS="$PHP_CLI_OBJS \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_SHARED_OBJS)"]) AS_CASE([$host_alias], [*aix*], [ diff --git a/sapi/cli/php.1.in b/sapi/cli/php.1.in index 30626015ce77..1972b1f87b4c 100644 --- a/sapi/cli/php.1.in +++ b/sapi/cli/php.1.in @@ -365,6 +365,15 @@ Shows configuration for extension .TP .B \-\-ini Show configuration file names +.TP +.B \-\-fpm +Run as +.BR php\-fpm (8), +passing the remaining arguments to it. Only available when PHP was configured +with \-\-enable\-cli\-fpm, and only recognized as the first argument. +Such a binary also runs as +.BR php\-fpm (8) +when invoked under a name starting with php\-fpm, e.g. through a symbolic link. .SH FILES .TP 15 .B php\-cli.ini diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 3702da89f9f0..f5604b96f64d 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -490,6 +490,9 @@ static void php_cli_usage(char *argv0) "\n" " --ini Show configuration file names\n" " --ini=diff Show INI entries that differ from the built-in default\n" +#ifdef PHP_CLI_WITH_FPM + " --fpm Run as php-fpm, passing the remaining arguments to it\n" +#endif "\n" " --rf Show information about function .\n" " --rc Show information about class .\n" diff --git a/sapi/cli/php_cli_main.c b/sapi/cli/php_cli_main.c index 1030b5feb923..b13066610f85 100644 --- a/sapi/cli/php_cli_main.c +++ b/sapi/cli/php_cli_main.c @@ -12,8 +12,26 @@ #include "php.h" #include "cli.h" +#ifdef PHP_CLI_WITH_FPM +#include "sapi/fpm/fpm/fpm.h" +#endif int main(int argc, char *argv[]) { +#ifdef PHP_CLI_WITH_FPM + /* Running as "php-fpm*" (e.g. a php-fpm symlink to php) or as + * "php --fpm [args]" runs the FPM SAPI. argv is passed as is because FPM + * re-executes it on reload; FPM options start after "--fpm". */ + if (argc > 0 && argv[0]) { + const char *name = strrchr(argv[0], '/'); + name = name ? name + 1 : argv[0]; + if (strncmp(name, "php-fpm", strlen("php-fpm")) == 0) { + return fpm_main(argc, argv, 1); + } + } + if (argc > 1 && strcmp(argv[1], "--fpm") == 0) { + return fpm_main(argc, argv, 2); + } +#endif return do_php_cli(argc, argv); } diff --git a/sapi/cli/tests/cli_fpm.phpt b/sapi/cli/tests/cli_fpm.phpt new file mode 100644 index 000000000000..0e15bc1e8eeb --- /dev/null +++ b/sapi/cli/tests/cli_fpm.phpt @@ -0,0 +1,38 @@ +--TEST-- +php --fpm runs the FPM SAPI +--SKIPIF-- +&1"), 'fpm-fcgi')) { + die("skip PHP was not built with --enable-cli-fpm"); +} +?> +--FILE-- + .*$/m', shell_exec("$php --fpm -n -i"), $m); +var_dump($m[0]); + +// Anywhere else it is an ordinary argument. +var_dump(shell_exec("$php -n -r 'echo \$argv[1];' -- --fpm")); + +// Running under a name starting with "php-fpm" also switches to the FPM SAPI. +$dir = __DIR__ . '/cli_fpm'; +@mkdir($dir); +symlink(realpath(getenv('TEST_PHP_EXECUTABLE')), "$dir/php-fpm8"); +preg_match('/^Server API => .*$/m', shell_exec(escapeshellarg("$dir/php-fpm8") . " -n -i"), $m); +var_dump($m[0]); +?> +--CLEAN-- + +--EXPECT-- +string(25) "Server API => FPM/FastCGI" +string(5) "--fpm" +string(25) "Server API => FPM/FastCGI" diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4 index 89c53a0c4d28..b2c293833965 100644 --- a/sapi/fpm/config.m4 +++ b/sapi/fpm/config.m4 @@ -1,10 +1,3 @@ -PHP_ARG_ENABLE([fpm], - [for FPM build], - [AS_HELP_STRING([--enable-fpm], - [Enable building of the fpm SAPI executable])], - [no], - [no]) - dnl Configure checks. AC_DEFUN([PHP_FPM_CLOCK], [ AC_CHECK_FUNCS([clock_gettime],, [ @@ -473,9 +466,18 @@ if test "$PHP_FPM" != "no"; then PHP_SELECT_SAPI([fpm], [program], - [$PHP_FPM_FILES $PHP_FPM_TRACE_FILES $PHP_FPM_SD_FILES], + [php_fpm_main.c], [-I$abs_srcdir/sapi/fpm -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) + dnl Everything except the main() entry point, so that the CLI binary can link + dnl the same objects for fpm_main() (--enable-cli-fpm). + PHP_ADD_SOURCES_X([sapi/fpm], + [$PHP_FPM_FILES $PHP_FPM_TRACE_FILES $PHP_FPM_SD_FILES], + [-I$abs_srcdir/sapi/fpm -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1], + [PHP_FPM_SHARED_OBJS]) + PHP_FPM_OBJS="$PHP_FPM_OBJS $PHP_FPM_SHARED_OBJS" + PHP_SUBST([PHP_FPM_SHARED_OBJS]) + AS_CASE([$host_alias], [*aix*], [ BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --tag=CC --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" @@ -489,4 +491,5 @@ if test "$PHP_FPM" != "no"; then PHP_SUBST([SAPI_FPM_PATH]) PHP_SUBST([BUILD_FPM]) PHP_SUBST([FPM_EXTRA_LIBS]) + AS_VAR_IF([PHP_CLI_FPM], [no],, [EXTRA_LIBS="$EXTRA_LIBS $FPM_EXTRA_LIBS"]) fi diff --git a/sapi/fpm/config0.m4 b/sapi/fpm/config0.m4 new file mode 100644 index 000000000000..d00da52b30e8 --- /dev/null +++ b/sapi/fpm/config0.m4 @@ -0,0 +1,6 @@ +PHP_ARG_ENABLE([fpm], + [for FPM build], + [AS_HELP_STRING([--enable-fpm], + [Enable building of the fpm SAPI executable])], + [no], + [no]) diff --git a/sapi/fpm/fpm/fpm.h b/sapi/fpm/fpm/fpm.h index ec036a2d6819..a018948c8bd2 100644 --- a/sapi/fpm/fpm/fpm.h +++ b/sapi/fpm/fpm/fpm.h @@ -41,6 +41,10 @@ enum fpm_init_return_status { }; int fpm_run(int *max_requests); +/* this performs full fpm-SAPI boot: the former main() of php-fpm. + * argv must be the process' original argv (it is re-executed on reload), + * FPM options are parsed starting at argv[first_arg]. */ +int fpm_main(int argc, char *argv[], int first_arg); enum fpm_init_return_status fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf, int run_as_root, int force_daemon, int force_stderr); struct fpm_globals_s { diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index 3d35e942a06e..d08ad1a640c2 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -1530,8 +1530,8 @@ static zend_module_entry cgi_module_entry = { STANDARD_MODULE_PROPERTIES }; -/* {{{ main */ -int main(int argc, char *argv[]) +/* {{{ fpm_main */ +int fpm_main(int argc, char *argv[], int first_arg) { int exit_status = FPM_EXIT_OK; int c, use_extended_info = 0; @@ -1592,6 +1592,7 @@ int main(int argc, char *argv[]) php_ini_builder_init(&ini_builder); + php_optind = first_arg; while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (c) { case 'c': diff --git a/sapi/fpm/php_fpm_main.c b/sapi/fpm/php_fpm_main.c new file mode 100644 index 000000000000..ab06cb4347d0 --- /dev/null +++ b/sapi/fpm/php_fpm_main.c @@ -0,0 +1,19 @@ +/* + +----------------------------------------------------------------------+ + | Copyright © The PHP Group and Contributors. | + +----------------------------------------------------------------------+ + | This source file is subject to the Modified BSD License that is | + | bundled with this package in the file LICENSE, and is available | + | through the World Wide Web at . | + | | + | SPDX-License-Identifier: BSD-3-Clause | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" +#include "fpm/fpm.h" + +int main(int argc, char *argv[]) +{ + return fpm_main(argc, argv, 1); +}