Jump to content

Odd exception in console


MarkE
 Share

Recommended Posts

In the process of refactoring and improving my FieldtypeMeasurement module, I came across an odd behaviour in the Tracy console. My module uses config php files including measurement conversion details which are in arrays which may include anonymous and named functions.

Previously I used $data = include $path; to get these config files, but that meant that I had to test for function existence (for named functions) in the config files. $data = include_once $path; doesn't work because include_once returns true (not the return value) on subsequent calls, so I decided on this:

		$data = include_once $path;
		if($data === true) {
			$data = $this->session->get($quantity . '_data');
		} else {
			$this->session->set($quantity . '_data', $data);
		}

That does the business, but if $data has anonymous function and I run the code from the console, I get this error:

Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in [no active file]:0 Stack trace: #0 {main} thrown in [no active file] on line 0

The odd thing is that the code all executes and outputs as expected - the 'fatal error' appears to be not at all fatal. Furthermore, if I run the exact same code from API calls in the main program, no exceptions are generated. I can't track down where the exception is being generated or why. I'm not particularly worried as everything seems to work OK, but it is a bit off-putting.

Any ideas?

Link to comment
Share on other sites

Hi @adrian - It is like:

return array(
///////Units Of Temperature///////
	"dimension" => new Dimension([Dimension::TEMPERATURE => 1]),
	'base' => 'Kelvin',
	'units' => array(
		"Kelvin" => array("shortLabel" => "K", "conversion" => 1, "plural" => "Kelvin"), //Kelvin - base unit for temperature
		"Celsius" => array("shortLabel" => "degC", "conversion" => function ($val, $tofrom) {
			return $tofrom ? $val - 273.15 : $val + 273.15;
		}, "plural" => "Celsius"),
		"Fahrenheit" => array("shortLabel" => "degF", "conversion" => function ($val, $tofrom) {
			return $tofrom ? ($val * 9 / 5 - 459.67) : (($val + 459.67) * 5 / 9);
		}, "plural" => "Fahrenheit"),
	)
);

 

Link to comment
Share on other sites

So that is the entire contents of the file at $path?

I just tested like this:

image.png.789a44c8251476c51fb4fcf8a5b54621.png

where test.php contains:

return array(
    ///////Units Of Temperature///////
        "dimension" => 'dfg',
        'base' => 'Kelvin',
        'units' => array(
            "Kelvin" => array("shortLabel" => "K", "conversion" => 1, "plural" => "Kelvin"), //Kelvin - base unit for temperature
            "Celsius" => array("shortLabel" => "degC", "conversion" => function ($val, $tofrom) {
                return $tofrom ? $val - 273.15 : $val + 273.15;
            }, "plural" => "Celsius"),
            "Fahrenheit" => array("shortLabel" => "degF", "conversion" => function ($val, $tofrom) {
                return $tofrom ? ($val * 9 / 5 - 459.67) : (($val + 459.67) * 5 / 9);
            }, "plural" => "Fahrenheit"),
        )
    );

All I did was change the value of dimension because I don't have that class set up.

What am I missing?

Link to comment
Share on other sites

39 minutes ago, adrian said:

So that is the entire contents of the file at $path?

Yes - apart from <?php namespace MetaTunes\MeasurementClasses; which is probably irrelevant to your test. The exception is not generated on the first include_once. It arises from the next bit which is to avoid $data just being == true on subsequent calls:

		if($data === true) {
			$data = $this->session->get($quantity . '_data');
		} else {
			$this->session->set($quantity . '_data', $data);
		}

EDIT: Of course, I don't know what actually generates the exception , so it may be in the code which executes the conversion function. All I do know is that without the above snippet, no exception is generated (and that it is not generated in any case outside the Tracy console context).

Link to comment
Share on other sites

It's due to setting that $data to a session. PHP serializes data saved in sessions, so that's the reason for the error. Here are a couple of suggestions:

https://stackoverflow.com/questions/39885355/php-serialization-of-a-closure-is-not-allowed

This isn't an issue with the Console panel - I get exactly the same error in a template file.

Link to comment
Share on other sites

Thanks @adrian. That's curious because I'm not getting the exception in a template file. It executes normally with the correct result and no exceptions:

1000694451_Measurementdebug.thumb.jpg.db9074a28e81eb8860ae10908fa9b0fc.jpg

DATA1 is the result of the include_once and DATA2 is after the test - i.e. if DATA1 is == true it is the session variable. Also, even in the console panel everything executes normally - the exception message seems to be spurious. However, I will investigate the stackoverflow link and report back anything of interest.

EDIT - should have expanded that second DATA2 to show the closure:

885539978_Measurementdebuga.jpg.30bdc591b01507ffa9526269fb48ea49.jpg

Edited by MarkE
Additional info
Link to comment
Share on other sites

Hi @adrian. What did you do to get an error in a template file - I can't replicate that? See above post - executes correctly with no errors - the code in the template was:

		$data = include_once 'M:\laragon\www\BawdHall\site-admin\modules\FieldtypeMeasurement\Config\Temperature.php';
		bd($data, 'data 1');
		if($data === true) {
			$data = $session->get('quantity' . '_data');
		} else {
			$session->set('quantity' . '_data', $data);
		}
		bd($data, 'data 2');
		$data = include_once 'M:\laragon\www\BawdHall\site-admin\modules\FieldtypeMeasurement\Config\Temperature.php';
		bd($data, 'data 1');
		if($data === true) {
			$data = $session->get('quantity' . '_data');
		} else {
			$session->set('quantity' . '_data', $data);
		}
		bd($data, 'data 2');

The link you provided yielded no insights as it failed to catch the supposed error. Also, it seems like the 'error' is not caught by tracyConsoleShutdownHandler() in CodeProcessor.php, so I'm not sure how further to track it down.

 

Link to comment
Share on other sites

Template file contains:

    $quantity = 'testing';
    $data = include_once '/Users/ajones/Sites/ecoreportcard/test.php';
    $this->session->set($quantity . '_data', $data);

and test.php contains:

return array(
    ///////Units Of Temperature///////
        "dimension" => 'dfg',
        'base' => 'Kelvin',
        'units' => array(
            "Kelvin" => array("shortLabel" => "K", "conversion" => 1, "plural" => "Kelvin"), //Kelvin - base unit for temperature
            "Celsius" => array("shortLabel" => "degC", "conversion" => function ($val, $tofrom) {
                return $tofrom ? $val - 273.15 : $val + 273.15;
            }, "plural" => "Celsius"),
            "Fahrenheit" => array("shortLabel" => "degF", "conversion" => function ($val, $tofrom) {
                return $tofrom ? ($val * 9 / 5 - 459.67) : (($val + 459.67) * 5 / 9);
            }, "plural" => "Fahrenheit"),
        )
    );

and the result when viewing a page with that template is:

Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in [no active file]:0 Stack trace: #0 {main} thrown in [no active file] on line 0

I think it really is a simple matter of what the error says. You aren't allowed to serialize closures (and there are two of them in test.php) and saving to $_SESSION serializes the data.

There are lots of topics discussing it: https://www.google.com/search?q=php+session+"Serialization+of+'Closure'+is+not+allowed"

 

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...