Skip to content

Invoke destructors during bailout #19080

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,8 @@ PHP 8.5 UPGRADE NOTES
. The high resolution timer (`hrtime()`) on macOS now uses the recommended
`clock_gettime_nsec_np(CLOCK_UPTIME_RAW)` API instead of
`mach_absolute_time()`.
. Destructors are now invoked correctly after bailout, to match the behavior
of shutdown handlers.

- CLI/CGI:
. The `-z` or `--zend-extension` option has been removed as it was
Expand Down
3 changes: 2 additions & 1 deletion Zend/tests/fibers/fatal-error-with-multiple-fibers.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ $fiber1 = new Fiber(function (): void {
try {
\Fiber::suspend(1);
} finally {
echo "not executed";
echo "executed";
}
});

Expand All @@ -28,3 +28,4 @@ int(2)
Deprecated: Passing E_USER_ERROR to trigger_error() is deprecated since 8.4, throw an exception or call exit with a string message instead in %s on line %d

Fatal error: Fatal error in fiber in %sfatal-error-with-multiple-fibers.php on line %d
executed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep the trailing newline

40 changes: 40 additions & 0 deletions Zend/tests/invoke_destructors_after_bailout.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
--TEST--
Invoke destructors after bailout
--SKIPIF--
<?php
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the test is limited to one second, I don't think that counts as slow

?>
--FILE--
<?php

final class StatCounter {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems more complicated than you need

<?php

class StatCounter {

    public function __construct(private array $stats) {}

    public function __destruct() {
        echo "Sending stats: ".json_encode($this->stats)."\n";
    }

}

$stats = new StatCounter(['test' => 1, 'test2' => 1]);

set_time_limit(1);
while (1);

should do the same thing

private static self $instance;
public static function get(): self {
return self::$instance ??= new self;
}

private array $stats = [];

private function __construct() {}

public function __destruct() {
echo "Sending stats: ".json_encode($this->stats)."\n";
}

public function inc(string $key, int $by = 1): void {
$this->stats[$key] ??= 0;
$this->stats[$key] += $by;
}
}

StatCounter::get()->inc('test');
StatCounter::get()->inc('test2');

set_time_limit(1);
while (1);

?>
--EXPECTF--

Fatal error: Maximum execution time of 1 second exceeded in %s on line %d
Sending stats: {"test":1,"test2":1}
9 changes: 9 additions & 0 deletions ext/zend_test/tests/observer_fiber_functions_03.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,12 @@ Fatal error: Allowed memory size of 104857600 bytes exhausted %s on line %d
<!-- destroy: %s -->
</Fiber::resume>
</file '%s'>
<!-- switching from fiber %s to %s -->
<destroying '%s'>
<!-- Exception: GracefulExit -->
</Fiber::suspend>
<!-- Exception: GracefulExit -->
</{closure:%s:%d}>
<!-- switching from fiber %s to %s -->
<destroyed '%s'>
<!-- destroy: %s -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep a trailing newline

1 change: 0 additions & 1 deletion main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1474,7 +1474,6 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c
if (!(orig_type & E_DONT_BAIL)) {
/* restore memory limit */
zend_set_memory_limit(PG(memory_limit));
zend_objects_store_mark_destructed(&EG(objects_store));
if (CG(in_compilation) && (type == E_COMPILE_ERROR || type == E_PARSE)) {
/* We bailout during compilation which may for example leave stale entries in CG(loop_var_stack).
* If code is compiled during shutdown, we need to make sure the compiler is reset to a clean state,
Expand Down