You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In our application multiple cron jobs running at the same time.
Circa every two hours (sporadically) we get an exception: Serialized data must be a string containing serialized PHP code; received:
Current behavior
The exception occurs because Laminas\Cache\Storage\Adapter\Filesystem::internalGetItem returns an empty string which cannot be deserialized by laminas/laminas-serializer/src/Adapter/PhpSerialize later on.
It turned out that cache files are created before filled and there is a short time slot where the file content is empty.
(the time slot is in Laminas\Cache\Storage\Adapter\Filesystem\LocalFilesystemInteraction::write after fopen and before flock)
Some micro- or milliseconds later the file is filled.
How to reproduce
Setup an application with laminas filesystem cache. The plugin serializer is enabled.
Add a debug break point to Laminas\Cache\Storage\Adapter\Filesystem\LocalFilesystemInteraction::write before flock is called the first time and after chmod is called (line 109 in 2.4.1).
Run into the break point with the debugger and keep the execution paused.
Disable debugger listening to the next request and ensure that the next request will not be blocked by the paused debug session.
Perform an asynchronous call that requests the same cache entry from filesystem cache.
Exception Serialized data must be a string containing serialized PHP code; received: should occur
I don't know if it would be possible to cover this case with a unit test (would require two asynchronous calls and a delay in chmod operation?)
Expected behavior
Laminas\Cache\Storage\Adapter\Filesystem::internalGetItem will always return with $success = false; or with the file content and never with empty content as a consequence of the file beeing created but the content not written yet (by Laminas\Cache\Storage\Adapter\Filesystem\LocalFilesystemInteraction::write).
Notes
The error would not occur on our system with the following workaround in Laminas\Cache\Storage\Adapter\Filesystem::internalGetItem before $success = true; is called:
Maybe there is a more reliable way to ensure that the created file will be filled when requested.
Maybe it would be possible to just return with $success = false; if the file content is empty and the serialize plugin is used (I don't know if an empty string is valid, if the serialize plugin is not used). However, without the serialize plugin an empty string could still be the result of a read/write bug.
The text was updated successfully, but these errors were encountered:
After testing different szeanarios we came to the conclustion that only two ways to create a cache file would solve the issue in LocalFilesystemInteraction's write method on our test environment:
file_put_contents with LOCK_EX flag
"fopen" a file with random suffix in filename and rename the file after "fclose" to the desired cache file name
As workaround we managed to inject a modified LocalFilesystemInteractionInteface to Filesystem. We implemented the solution with random suffix in filename of a temporary file in the "non-blocking" code path.
Bug Report
Summary
In our application multiple cron jobs running at the same time.
Circa every two hours (sporadically) we get an exception:
Serialized data must be a string containing serialized PHP code; received:
Current behavior
The exception occurs because
Laminas\Cache\Storage\Adapter\Filesystem::internalGetItem
returns an empty string which cannot be deserialized bylaminas/laminas-serializer/src/Adapter/PhpSerialize
later on.It turned out that cache files are created before filled and there is a short time slot where the file content is empty.
(the time slot is in
Laminas\Cache\Storage\Adapter\Filesystem\LocalFilesystemInteraction::write
afterfopen
and beforeflock
)Some micro- or milliseconds later the file is filled.
How to reproduce
serializer
is enabled.Laminas\Cache\Storage\Adapter\Filesystem\LocalFilesystemInteraction::write
beforeflock
is called the first time and afterchmod
is called (line 109 in 2.4.1).Serialized data must be a string containing serialized PHP code; received:
should occurI don't know if it would be possible to cover this case with a unit test (would require two asynchronous calls and a delay in
chmod
operation?)Expected behavior
Laminas\Cache\Storage\Adapter\Filesystem::internalGetItem
will always return with$success = false;
or with the file content and never with empty content as a consequence of the file beeing created but the content not written yet (byLaminas\Cache\Storage\Adapter\Filesystem\LocalFilesystemInteraction::write
).Notes
Laminas\Cache\Storage\Adapter\Filesystem::internalGetItem
before$success = true;
is called:$success = false;
if the file content is empty and theserialize
plugin is used (I don't know if an empty string is valid, if theserialize
plugin is not used). However, without theserialize
plugin an empty string could still be the result of a read/write bug.The text was updated successfully, but these errors were encountered: