@@ -2037,19 +2037,20 @@ jobs:
20372037 ../bashunit assert not_contains 'Ds\Seq' "$OUTPUT"
20382038 - script : |
20392039 cd e2e/bug-15407
2040- XDEBUG_HANDLER_DEBUG=1 ../../bin/phpstan analyse --no-progress 2>&1 | tee -a output.txt
2041- ../bashunit assert file_contains output.txt "Process restarting "
2040+ ../../bin/phpstan analyse --no-progress -vvv 2>&1 | tee -a output.txt
2041+ ../bashunit assert file_contains output.txt "Restarting process: pcov (pcov.enabled=1) "
20422042 coverage: "pcov"
20432043 - script : |
20442044 cd e2e/bug-15407
2045- XDEBUG_HANDLER_DEBUG=1 ../../bin/phpstan analyse --no-progress 2>&1 | tee -a output.txt
2046- ../bashunit assert file_contains output.txt "Process restarting "
2045+ ../../bin/phpstan analyse --no-progress -vvv 2>&1 | tee -a output.txt
2046+ ../bashunit assert file_contains output.txt "Restarting process: pcov (pcov.enabled=1) "
20472047 coverage: "pcov"
20482048 ini-values: "pcov.enabled=1"
20492049 - script : |
20502050 cd e2e/bug-15407
2051- XDEBUG_HANDLER_DEBUG=1 ../../bin/phpstan analyse --no-progress 2>&1 | tee -a output.txt
2052- ../bashunit assert file_not_contains output.txt "Process restarting"
2051+ # the restart may still happen to activate OPcache, just not for pcov
2052+ ../../bin/phpstan analyse --no-progress -vvv 2>&1 | tee -a output.txt
2053+ ../bashunit assert file_not_contains output.txt "pcov (pcov.enabled"
20532054 coverage: "pcov"
20542055 ini-values: "pcov.enabled=0"
20552056
@@ -2117,8 +2118,8 @@ jobs:
21172118 run : make build-turbo
21182119
21192120 - name : " Load the turbo extension through php.ini"
2120- # TurboProcessRestarter re-executes the process with the loaded php. ini
2121- # to activate OPcache; an extension passed as -d would not survive that,
2121+ # the restart re-executes the process with the loaded ini files to
2122+ # activate OPcache; an extension passed as -d would not survive that,
21222123 # one from the ini scan dir is loaded again
21232124 run : |
21242125 echo "extension=$PWD/turbo-ext/phpstan_turbo.so" | sudo tee "$(php -r 'echo PHP_CONFIG_FILE_SCAN_DIR;')/99-phpstan-turbo.ini"
@@ -2246,8 +2247,8 @@ jobs:
22462247 make -j"$(nproc)"
22472248
22482249 - name : " Load both extensions through php.ini"
2249- # TurboProcessRestarter re-executes the process with the loaded php. ini
2250- # to activate OPcache; extensions passed as -d would not survive that,
2250+ # the restart re-executes the process with the loaded ini files to
2251+ # activate OPcache; extensions passed as -d would not survive that,
22512252 # ones from the ini scan dir are loaded again
22522253 run : |
22532254 printf 'extension=%s\nextension=%s\n' "$PWD/turbo-ext/phpstan_turbo.so" "$RUNNER_TEMP/forkunsafe/modules/forkunsafe.so" | sudo tee "$(php -r 'echo PHP_CONFIG_FILE_SCAN_DIR;')/99-phpstan-turbo.ini"
@@ -2281,3 +2282,189 @@ jobs:
22812282 echo "$OUTPUT"
22822283 ../bashunit assert contains 'Mechanism: fork (pcntl_fork)' "$OUTPUT"
22832284 ../bashunit assert contains '[OK] No errors' "$OUTPUT"
2285+
2286+ process-restart-e2e-tests :
2287+ name : " Process restart E2E tests"
2288+ runs-on : ${{ matrix.operating-system }}
2289+ timeout-minutes : 30
2290+
2291+ defaults :
2292+ run :
2293+ shell : bash
2294+
2295+ strategy :
2296+ fail-fast : false
2297+ matrix :
2298+ include :
2299+ # pcov armed: one restart, every process - the forked worker
2300+ # included, which no per-worker `-d` injection could reach - runs
2301+ # disarmed. pcov stays loaded: the rows disarm rather than unload,
2302+ # which keeps the extension's own symbols reflectable. setup-php
2303+ # loads OPcache dormant on CLI, so the same restart activates it in
2304+ # every Linux row
2305+ - operating-system : " ubuntu-latest"
2306+ coverage : " pcov"
2307+ extensions : " "
2308+ script : |
2309+ php ../../bin/phpstan analyse --no-progress
2310+ php check.php restarted-for=pcov,opcache pcov-armed=no pcov-loaded=yes opcache-cli-on=yes processes=2+ starts=2
2311+
2312+ # Windows has no pcntl_exec, so the restart runs as a child process
2313+ # whose exit code is passed on. OPcache is left alone there: the
2314+ # workers are spawned, and ProcessHelper activates it for each
2315+ - operating-system : " windows-latest"
2316+ coverage : " pcov"
2317+ extensions : " "
2318+ script : |
2319+ php ../../bin/phpstan analyse --no-progress
2320+ php check.php restarted-for=pcov pcov-armed=no processes=1+ starts=2
2321+ set +e
2322+ php ../../bin/phpstan analyse --no-progress --configuration failing.neon
2323+ EXIT_CODE=$?
2324+ set -e
2325+ if [ "$EXIT_CODE" != "1" ]; then
2326+ echo "FAIL: the restarted process' exit code was not passed on, got $EXIT_CODE"
2327+ exit 1
2328+ fi
2329+
2330+ # xdebug: one restart disarms it via xdebug.mode=off, and it stays
2331+ # loaded so xdebug_*() remains reflectable. No note about it being
2332+ # active either
2333+ - operating-system : " ubuntu-latest"
2334+ coverage : " xdebug"
2335+ extensions : " "
2336+ script : |
2337+ php ../../bin/phpstan analyse --no-progress 2>&1 | tee out.txt
2338+ if grep -q 'The Xdebug PHP extension is active, but' out.txt; then
2339+ echo "FAIL: xdebug survived the restart armed"
2340+ exit 1
2341+ fi
2342+ php check.php restarted-for=xdebug,opcache xdebug-armed=no xdebug-loaded=yes processes=2+ starts=2
2343+
2344+ # XDEBUG_MODE overrides xdebug.mode, so flagging the ini alone would
2345+ # be silently overridable - the row exports the env var too
2346+ - operating-system : " ubuntu-latest"
2347+ coverage : " xdebug"
2348+ extensions : " "
2349+ script : |
2350+ XDEBUG_MODE=develop,debug php ../../bin/phpstan analyse --no-progress
2351+ php check.php restarted-for=xdebug,opcache xdebug-armed=no xdebug-loaded=yes processes=2+ starts=2
2352+
2353+ # --xdebug keeps xdebug armed and does not restart for it - only for
2354+ # OPcache
2355+ - operating-system : " ubuntu-latest"
2356+ coverage : " xdebug"
2357+ extensions : " "
2358+ script : |
2359+ php ../../bin/phpstan analyse --no-progress --xdebug 2>&1 | tee out.txt
2360+ if ! grep -q 'enabled, and the Xdebug PHP extension is active' out.txt; then
2361+ echo "FAIL: --xdebug did not keep xdebug"
2362+ exit 1
2363+ fi
2364+ php check.php restarted-for=opcache xdebug-armed=yes processes=1+ starts=2
2365+
2366+ # xdebug and pcov together: one restart handles both. Both come in
2367+ # through `extensions` because setup-php's `coverage: xdebug` unloads
2368+ # pcov. xdebug is armed by its default mode, pcov on the command
2369+ # line - which also proves the composed ini carries runtime `-d`
2370+ # overrides over without reconstructing them from $argv
2371+ - operating-system : " ubuntu-latest"
2372+ coverage : " "
2373+ extensions : " xdebug, pcov"
2374+ script : |
2375+ php -d pcov.enabled=1 ../../bin/phpstan analyse --no-progress
2376+ php check.php restarted-for=xdebug,pcov,opcache pcov-armed=no xdebug-armed=no processes=2+ starts=2
2377+
2378+ # --xdebug with pcov armed: xdebug stays armed, pcov is still
2379+ # disarmed by the same restart - something xdebug-handler could never
2380+ # express
2381+ - operating-system : " ubuntu-latest"
2382+ coverage : " "
2383+ extensions : " xdebug, pcov"
2384+ script : |
2385+ php -d pcov.enabled=1 ../../bin/phpstan analyse --no-progress --xdebug
2386+ php check.php restarted-for=pcov,opcache pcov-armed=no xdebug-armed=yes processes=1+ starts=2
2387+
2388+ # uopz rewrites opcodes unless uopz.disable=1
2389+ - operating-system : " ubuntu-latest"
2390+ coverage : " none"
2391+ extensions : " uopz"
2392+ script : |
2393+ php ../../bin/phpstan analyse --no-progress
2394+ php check.php restarted-for=uopz,opcache uopz-armed=no processes=2+ starts=2
2395+
2396+ # OPcache is dormant on CLI by default - the restart activates it,
2397+ # and the forked workers inherit the parent's warm opcode cache
2398+ - operating-system : " ubuntu-latest"
2399+ coverage : " none"
2400+ extensions : " opcache"
2401+ script : |
2402+ php -d opcache.enable_cli=0 ../../bin/phpstan analyse --no-progress -vvv > out.txt 2>&1
2403+ cat out.txt
2404+ php check.php restarted-for=opcache opcache-cli-on=yes processes=2+ starts=2
2405+ if ! grep -qE 'Mechanism: +fork' out.txt; then
2406+ echo "FAIL: the workers were not forked under the activated OPcache"
2407+ exit 1
2408+ fi
2409+
2410+ # --debug restarts like any other run - it only makes the analysis
2411+ # serial, --xdebug is what keeps xdebug
2412+ - operating-system : " ubuntu-latest"
2413+ coverage : " pcov"
2414+ extensions : " "
2415+ script : |
2416+ php ../../bin/phpstan analyse --no-progress --debug
2417+ php check.php restarted-for=pcov,opcache pcov-armed=no processes=1 starts=2
2418+
2419+ # diagnose never restarts either, it reports what a run would do
2420+ - operating-system : " ubuntu-latest"
2421+ coverage : " pcov"
2422+ extensions : " "
2423+ script : |
2424+ php ../../bin/phpstan diagnose 2>&1 | tee out.txt
2425+ if ! grep -qE 'Restart if started now: +yes - pcov' out.txt; then
2426+ echo "FAIL: diagnose did not report the restart it would perform"
2427+ exit 1
2428+ fi
2429+
2430+ steps :
2431+ - name : Harden the runner (Audit all outbound calls)
2432+ uses : step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
2433+ with :
2434+ egress-policy : audit
2435+
2436+ - name : " Checkout"
2437+ uses : actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
2438+ with :
2439+ persist-credentials : false
2440+
2441+ - name : " Install PHP"
2442+ uses : " shivammathur/setup-php@eb7c497e18156a6bbabfef1d3a82760b9eda3962" # 2.40.0
2443+ with :
2444+ coverage : ${{ matrix.coverage }}
2445+ php-version : " 8.2"
2446+ extensions : ${{ matrix.extensions }}
2447+
2448+ - uses : " ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0
2449+
2450+ - name : " Test"
2451+ working-directory : " e2e/restart-manager"
2452+ env :
2453+ SCRIPT : ${{ matrix.script }}
2454+ # Symfony wraps its notes to the terminal width and prefixes wrapped
2455+ # lines with "!", which can split a phrase in a way no post-processing
2456+ # rejoins - and would make the negative assertions pass vacuously
2457+ COLUMNS : " 400"
2458+ run : |
2459+ # count every start of the main process, the one before the restart
2460+ # included - which only an ini-level hook sees
2461+ LINE=$(php -r 'echo "auto_prepend_file=\"", getcwd(), DIRECTORY_SEPARATOR, "start-log.php\"";')
2462+ INI=$(php -r 'echo php_ini_loaded_file();')
2463+ if [ "$RUNNER_OS" = "Windows" ]; then
2464+ echo "$LINE" >> "$INI"
2465+ else
2466+ echo "$LINE" | sudo tee -a "$INI" > /dev/null
2467+ fi
2468+ php ../../bin/phpstan clear-result-cache
2469+ rm -f probe.log starts.log
2470+ eval "$SCRIPT"
0 commit comments