|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #62452 Variable Aliasing does not work in Closure
Submitted: 2012-06-29 19:53 UTC Modified: 2015-03-10 21:06 UTC
Avg. Score:3.7 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:2 (66.7%)
Same OS:2 (66.7%)
From: hanskrentel at yahoo dot de Assigned: nikic (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: Irrelevant OS: Multiple
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Bug Type:
From: hanskrentel at yahoo dot de
New email:
PHP Version: OS:


 [2012-06-29 19:53 UTC] hanskrentel at yahoo dot de
It's not possible to make use of variable aliasing in PHP when the alias is used 
within the use clause of a lambda function construct that is assigned to that 
variable (recursion).

PHP denies to do what it is commanded with a Fatal error: Cannot destroy active 
lambda function. But the function is not destroyed. It's just not that the 
variable container contains the identifier of it.

I'd like to change that, and I don't want to waste another variable name. Also I 
don't understand how I can actually destroy something I should not have any 
to from PHP userland.

Or if that is intended, please allow us to destroy the active lambda making the 
function return NULL and continue to execute.

Test script:
$f = function() use (&$f) {
    $f = function() {echo "hello"};

Expected result:

Actual result:
Fatal error: Cannot destroy active lambda function 


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2012-06-29 20:05 UTC]
Verified on master.
 [2012-06-29 20:05 UTC]
-Status: Open +Status: Verified -Package: *General Issues +Package: Scripting Engine problem
 [2012-07-02 07:03 UTC]
you can not destroy a closure while you are calling it.

when you override $f in $f, zend vm try to destroy the closure $f, since the 
refcout of it is 1.

try following :

$b = $f = function() use (&$f) {
    $f = function() {};
 [2012-07-02 07:03 UTC]
-Status: Verified +Status: Wont fix
 [2012-07-03 17:39 UTC] hanskrentel at yahoo dot de
hi @laurence, thank's for taking the time to review it. If I write code like


it does not fatal error either (you can not destroy a object while you are calling 

Also I don't want to destroy the closure, I just want to re-use that variable. 
Can't you just let the garbage collector do the dirty work?
 [2012-07-03 17:49 UTC]
-Status: Wont fix +Status: Re-Opened
 [2012-07-03 17:49 UTC]
@laruence: The closure can still exist even if it is not referenced by $f anymore. I didn't look into this yet, but the fix should be along the lines of adding a ref to the closure when it is called and removing it again when it finishes running. Actually, I remember seeing something in the code that backs up the function zval into op_array.prototype (disguised as a zend_function*) and dtors it in the leave_helper. But clearly that isn't enough yet.
 [2012-09-15 15:42 UTC]
I just looked into this a bit but couldn't find a good way to fix it. The main issue is that the prototype hack is only done in ZEND_INIT_FCALL_BY_NAME and only for VARs. Doing the same for CVs (as in this case) would be easy, but it sadly does not work properly if the closure is also invoked using call_user_func or any other function using zend_call_function internally. zend_call_function does not back the closure into the prototype and due to the way it works I'm not sure how this could be added there. For zcf the get_closure object handler call is done within zend_is_callable_ex and the results are put into the passed function_call_cache then. But the fcc can be reused for multiple calls (or not be used at all), so I really don't know how to do this safely without causing leaks or double frees.
 [2013-10-22 10:33 UTC] john dot papaioannou at gmail dot com
This bug is really annoying. Here's another scenario that I just hit while refactoring:

set_exception_handler(function($exception) {
    restore_exception_handler(); // boom
    echo "Exception handled, move along.\n";

throw new Exception; // fatal error: cannot destroy active lambda
 [2013-10-22 11:27 UTC] hanskrentel at yahoo dot de
@john dot papaioannou: If it helps, you can prevent the error in your case by assigning the closure to a variable first, so that the exception handler can be reset without destroying the closure (here: $handler):

set_exception_handler($handler = function($exception) {
    restore_exception_handler(); // boom
    echo "Exception handled, move along.\n";

throw new Exception; // fatal error gone now


I know that this does not fix the underlying problem, just commenting in the hope this might be helpful for you.
 [2015-03-10 21:06 UTC]
-Status: Re-Opened +Status: Closed -Assigned To: +Assigned To: nikic
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Sat Feb 22 16:01:28 2020 UTC