11<?php declare (strict_types=1 );
22
33/**
4- * Test for Runtime ::exitImmediately().
4+ * Test for ForkedChild ::exitImmediately().
55 *
66 * A pcntl_fork()ed child inherits the parent's whole process, and PHP's
77 * exit() runs the full teardown there: destructors, then every extension's
1717 * Two passes over the same child:
1818 * 1. control, plain exit() - the child must still be alive at the deadline
1919 * (proves the workload hangs)
20- * 2. exitImmediately() from a shutdown function - the child must be gone
21- * well within the deadline, with exit()'s status, the earlier shutdown
22- * function's marker written and the destructor's not
20+ * 2. the native exitImmediately() from a shutdown function - the child must
21+ * be gone well within the deadline, with exit()'s status, the earlier
22+ * shutdown function's marker written and the destructor's not
23+ *
24+ * The PHP twin, which runs without the active extension, must throw
25+ * TurboNotActiveException instead.
2326 *
2427 * Run: php -d extension=$PWD/phpstan_turbo.so tests/exit-immediately.php
2528 */
2629
2730const DEADLINE_SECONDS = 3 ;
2831const EXIT_STATUS = 7 ;
2932
30- if (!extension_loaded ('phpstan_turbo ' )) {
31- fwrite (STDERR , "phpstan_turbo extension is not loaded \n" );
32- exit (1 );
33- }
3433if (!function_exists ('pcntl_fork ' )) {
3534 echo "SKIP: pcntl is not available \n" ;
3635 exit (0 );
3736}
3837
38+ // declares the native class as PHPStanTurbo\ForkedChild next to the PHP twin
39+ require __DIR__ . '/activate-prefixed.php ' ;
40+
3941final class WedgedTeardown
4042{
4143
@@ -57,9 +59,10 @@ public function __destruct()
5759}
5860
5961/**
62+ * @param class-string|null $terminator
6063 * @return array{exited: bool, status: int|null, markers: string}
6164 */
62- function forkAndExit (bool $ terminate ): array
65+ function forkAndExit (? string $ terminator ): array
6366{
6467 $ markers = tmpfile ();
6568 if ($ markers === false ) {
@@ -78,9 +81,9 @@ function forkAndExit(bool $terminate): array
7881 register_shutdown_function (static function () use ($ markers ): void {
7982 fwrite ($ markers , "shutdown \n" );
8083 });
81- if ($ terminate ) {
82- register_shutdown_function (static function (): void {
83- PHPStanTurbo \ Runtime ::exitImmediately ();
84+ if ($ terminator !== null ) {
85+ register_shutdown_function (static function () use ( $ terminator ) : void {
86+ $ terminator ::exitImmediately ();
8487 });
8588 }
8689 exit (EXIT_STATUS );
@@ -110,11 +113,19 @@ function forkAndExit(bool $terminate): array
110113 return ['exited ' => $ exited , 'status ' => $ status , 'markers ' => $ written ];
111114}
112115
113- $ control = forkAndExit (false );
116+ $ control = forkAndExit (null );
114117printf ("control (exit): exited %s, markers %s \n" , $ control ['exited ' ] ? 'yes ' : 'no ' , json_encode ($ control ['markers ' ]));
115118
116- $ terminated = forkAndExit (true );
117- printf ("exitImmediately(): exited %s, status %s, markers %s \n" , $ terminated ['exited ' ] ? 'yes ' : 'no ' , var_export ($ terminated ['status ' ], true ), json_encode ($ terminated ['markers ' ]));
119+ $ terminated = forkAndExit (\PHPStanTurbo \ForkedChild::class);
120+ printf ("native: exited %s, status %s, markers %s \n" , $ terminated ['exited ' ] ? 'yes ' : 'no ' , var_export ($ terminated ['status ' ], true ), json_encode ($ terminated ['markers ' ]));
121+
122+ $ twinThrew = false ;
123+ try {
124+ \PHPStan \Turbo \ForkedChild ::exitImmediately ();
125+ } catch (\PHPStan \Turbo \TurboNotActiveException ) {
126+ $ twinThrew = true ;
127+ }
128+ printf ("PHP twin: threw TurboNotActiveException %s \n" , $ twinThrew ? 'yes ' : 'no ' );
118129
119130if ($ control ['exited ' ] || $ control ['markers ' ] !== "shutdown \ndestructor \n" ) {
120131 fwrite (STDERR , "FAIL: the control child did not wedge in its destructor - the workload no longer models the hang \n" );
@@ -132,5 +143,9 @@ function forkAndExit(bool $terminate): array
132143 fwrite (STDERR , "FAIL: unexpected teardown ran in the child \n" );
133144 exit (1 );
134145}
146+ if (!$ twinThrew ) {
147+ fwrite (STDERR , "FAIL: the PHP twin's exitImmediately() did not throw TurboNotActiveException \n" );
148+ exit (1 );
149+ }
135150
136151echo "ALL OK \n" ;
0 commit comments