Skip to content
Closed
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 NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ PHP NEWS
. Fixed bug GH-21603 (Missing addref for __unset). (ilutov)
. Fixed bug GH-21760 (Trait with class constant name conflict against
enum case causes SEGV). (Pratik Bhujel)
. Fixed GH-22010 (Exception thrown in destructor during shutdown causes a
memory leak). (Weilin Du)

- CLI:
. Fixed bug GH-21754 (`--rf` command line option with a method triggers
Expand Down
22 changes: 22 additions & 0 deletions Zend/tests/gh22010.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
GH-22010: Exception thrown in destructor during shutdown
--FILE--
<?php

class A
{
public function __destruct()
{
throw new Exception(__METHOD__);
}
}

$a = new A;

?>
--EXPECTF--
Fatal error: Uncaught Exception: A::__destruct in %s:%d
Stack trace:
#0 [internal function]: A->__destruct()
#1 {main}
thrown in %s on line %d
7 changes: 6 additions & 1 deletion Zend/zend_objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,12 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
}
}

zend_call_known_instance_method_with_0_params(destructor, object, NULL);
zend_try {
zend_call_known_instance_method_with_0_params(destructor, object, NULL);
} zend_catch {
OBJ_RELEASE(object);
zend_bailout();
} zend_end_try();

if (old_exception) {
if (EG(current_execute_data)) {
Expand Down
7 changes: 6 additions & 1 deletion Zend/zend_objects_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_call_destructors(zend_objects_sto
if (obj->handlers->dtor_obj != zend_objects_destroy_object
|| obj->ce->destructor) {
GC_ADDREF(obj);
obj->handlers->dtor_obj(obj);
zend_try {
obj->handlers->dtor_obj(obj);
} zend_catch {
GC_DELREF(obj);
zend_bailout();
} zend_end_try();
GC_DELREF(obj);
}
}
Expand Down