Update a current 3.10-dev installation which has Zend Opcache enabled and working to the latest 4.1 nightly by using the custom update URL https://update.joomla.org/core/nightlies/next_minor_list.xml or the previously downloaded update package https://developer.joomla.org/nightlies/Joomla_4.1.0-dev-Development-Update_Package.zip .
Works without any glitch.
When the files have been updated but (I think) before the database updates, a blank page is shown with an error message in the title (full error message see tool tip):
Tool tip a bit bigger:
When reloading the page, the update resumes and finishes as usual:
This does not happen when updating from 3.10 to 4.0 or from 4.0 to 4.1, as far as I know. Not sure now. I never observed it before with 4.0, but that might just have been luck.
Current 3.10-dev branch, clean installation, PHP 7.4 with opcache enabled, MySQL 8.0.27, Apache on Linux server, updating to latest Joomla 4.1 nightly.
Labels |
Added:
No Code Attached Yet
|
@dgrammatiko I think your hunch is right, and it could be a similar if not the same reason why we have to mock some methods from the filesystem class like File or Folder in the "administrator/components/com_joomlaupdate/finalisation.php" file.
I remember having debugged that once and found that sometimes it needs these mocks and sometimes not, on the same environment with the same starting conditions, and I have never found any reason for that.
Maybe @nikosdion has investigated that in past and an idea when and why it needs these mocks and if that could be the same here, autoloader not ready or something like that, depending on timings maybe?
The File and Folder mocked classes in the update.php should be fine as that file is an entry point (an application) that doesn't extend any of the known applications (CLI, Administrator, Site, etc). The finalization though should (?) be called from the AdministratorApplication thus all the JLoader classes should be there (?). Anyway, @nikosdion probably got all the answers here
The File and Folder mocked classes in the update.php should be fine as that file is an entry point (an application) that doesn't extend any of the known applications (CLI, Administrator, Site, etc).
Hmm, right ... I always forget that but should know it.
As soon as anybody else beside me can reproduce this so we can be sure it's not an error in my environment, we should make it a release blocker ... but not before.
When you reload that page, does the update resume and finish?
yes, I could successfully update with ctrl+F5
BTW this was on NginX + PHP 8.0.8 + MySQL 5.7.34
finalisation.php
usedThe finalization though should (?) be called from the AdministratorApplication thus all the JLoader classes should be there (?).
No. The finalisation.php
file is loaded from extract.php right after the extraction is over, outside Joomla's execution. It's at the very end of the file, under the finalizeUpdate
case. It is CRITICALLY IMPORTANT to keep it that way. Joomla may move its core files around. If we don't remove the old files (and clean up the OPcache) the next Joomla pageload will load a mix of old and new files and result in a broken site.
My tests were inconclusive here, although I manage to get an error (I forgot to enable debug so it might be this or some random glitch)
That's an issue with your server. You are using Windows, right? The most common mistake causing that is using the Thread Safe PHP binary with PHP FPM. See https://www.dionysopoulos.me/improve-php-performance-on-windows.html under “PHP versions, bits and thread safety”. Using the wrong thread safety works fairly well until you start having request concurrency or a cadence of request to trigger whatever issue is caused by recycling the PHP threads in PHP-FPM.
The first time we try to load the DB driver post-update is in JoomlaInstallerScript::update()
. However, this is only called through JoomlaUpdate's UpdateModel (Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel
) in the finaliseUpgrade
method, called after including the administrator/components/com_admin/script.php
file.
At this point we have finished extracting the update ZIP archive and executed the filesystem cleanup in finalisation.php
. Therefore the next Joomla pageload, the one which calls Joomla Update's update.finalise task, will work correctly. In @richard67 's case it did not.
Since the first time it failed saying it cannot find the class and the second time it worked it appears to be an OPcache issue and the affected file whose cache is not cleared is libraries/classmap.php
.
Indeed, since you are updating from Joomla 3.10, we do NOT reset the OPcache for each file we are writing to disk. We call opcache_reset
which is supposed to clear the entire OPcache upon the script exiting. However, I am not entirely convinced that this is instantaneous and I don't read enough C code to check the PHP source. If it does take some time and the time between calling it in the post-extraction finalisation.php
and calling the update.finalise task which loads Joomla again is not enough for the OPcache to actually clear you would indeed get the problem you mentioned.
In Joomla 4's extract.php
we address that by clearing the OPcache for each and every extracted .php
file.
For Joomla 3.10 the only thing we could do is add an arbitrary time delay, maybe something like 2–5 seconds, before we redirect to the update.finalise task. This means changing media/com_joomlaupdate/js/update.js
in Joomla 3.10 line 238 so that finalizeUpdate()
is not called immediately but after a short delay.
I am now going to make myself a really big, very caffeinated coffee. Diving into the internals of two versions of Joomla Update first thing in the morning was a bit too hardcore even for me
Un doppio doppio doppio espresso, per favore
Hmm, I've just checked and it seems it's exactly what @nikosdion supposed. I still had opcache on with SHM caching from some past test long ago so I have forgotten about it in the mean time. Will switch off and test again later.
Confirmed. It does not happen when opcache is disabled. Will update title and description.
Title |
|
If you can consistently reproduce this with OPcache do the change in update.js and give it another go. I have a feeling that would work.
@dgrammatiko Can you check if you have opcache enabled on your environment?
If it turns out to be opcache and page reload helps, we should add something to the 4.x FAQ that when updating from 3.10 and that happens, one should just reload the page to get the update finished.
As a hunch, I'd set opcache.revalidate_freq
in php.ini to something quite longer than 2 seconds. Possibly 120 seconds (ideally, set this to 2x the time it takes for the Joomla 3.10 to 4.x update to download and run on your machine). This would prevent OPcache from figuring out by itself that the file has changed.
For Joomla 3.10 the only thing we could do is add an arbitrary time delay, maybe something like 2–5 seconds, before we redirect to the update.finalise task. This means changing media/com_joomlaupdate/js/update.js in Joomla 3.10 line 238 so that finalizeUpdate() is not called immediately but after a short delay.
I'm happy to accept such a workaround when that works but I dont have a server with such configuration. @richard67 can you give it a try and send a PR?
I'm happy to accept such a workaround when that works but I dont have a server with such configuration. @richard67 can you give it a try and send a PR?
Will do later today, and if @dgrammatiko can reproduce too that it only happens with opcache, we would have one tester and one author (the one or the other way).
@richard67 OPCache was/is enabled with these settings (MAMP default)
@richard67 OPCache was/is enabled with these settings (MAMP default)
@dgrammatiko Can you confirm that it works fine when opcache is disabled?
@dgrammatiko Could you do the PR for 3.10-dev? My knowledge on JS, especially asynchronous execution, is too little.
@richard67 #36841 (but I haven't tested it)
@richard67 #36841 (but I haven't tested it)
I will test later today.
Status | New | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2022-01-25 12:03:03 |
Closed_By | ⇒ | richard67 |
Closing as having a pull request. It's for 3.10-dev as the investigations above have shown the problem has to be handled there.
Tthe problem probably is related to the alias of the namespavced class, in 3.10 the driver is
JDatabaseDriverMysqli
In 4.1 it's
\Joomla\Database\Mysqli\MysqliDriver
My hunch is that the alias is not yet established...