#56966 closed defect (bug) (fixed)
Updating plugins with WP6.1 creates .maintenance file and leaves it
Reported by: | jsh4 | Owned by: | desrosj |
---|---|---|---|
Milestone: | 6.1.1 | Priority: | normal |
Severity: | normal | Version: | 6.1 |
Component: | Upgrade/Install | Keywords: | has-testing-info has-patch commit fixed-major |
Focuses: | Cc: |
Description
Pre WP6.1 updating a plug in creates a .maintenance file and removes it when updates are complete. WP6.1 creates and leaves in place the .maintenance file requiring a shell action to remove it.
Change History (33)
#3
in reply to:
↑ 2
@
2 years ago
Replying to afragen:
Can you provide some data about your environment? Was anything missing afterwards?
Once I remove the .maintenance file manually, everything works fine.
My environment is getting older so maybe aging PHP version might have something to do with this.
This also happens when updating themes. Interesting, the .maintenance file isn't being created during WP core update.
I'm working my way through all my WP sites one by one learning all this as I go.
#4
@
2 years ago
I spoke too soon about WP updates not created a .maintenance file. It does... it just takes a while to show I guess during the actual code update moment.
My work around for dealing with this is to perform all other updates before I upgrade to 6.1.
#5
follow-up:
↓ 6
@
2 years ago
- Keywords reporter-feedback added
Hi @jsh4, can you post the following information?
- PHP Version
- Server software (Apache, NGINX, or?)
- Does this occur when updating one plugin, or when bulk updating, or both?
- Does this occur with all plugins disabled, then updating them?
This should help with reproducing the problem and tracking down the cause
#6
in reply to:
↑ 5
@
2 years ago
Replying to costdev:
Hi @jsh4, can you post the following information?
- PHP Version
7.4.21 (CLI)
- Server software (Apache, NGINX, or?)
It's an NGINX front end passing off to Apache2.
Apache/2.4.48 (Ubuntu)
- Does this occur when updating one plugin, or when bulk updating, or both?
Both.
- Does this occur with all plugins disabled, then updating them?
I haven't tried that. Just trying to get WP up to 6.1 on all the sites first.
This should help with reproducing the problem and tracking down the cause
Thanks for your help.
#7
@
2 years ago
- Keywords has-testing-info needs-testing added; reporter-feedback removed
Thanks @jsh4! I'll see if I can reproduce the issue.
For others reading this, please help test updating plugins in 6.1 on PHP 7.4.21 and NGINX passing off to Apache (or test on NGINX or Apache directly - more testing the better!).
#8
@
2 years ago
I have the same issue as reported by jsh4. I did some more investigation: I'm using the ftpext method in my config.inc.php:
define('FS_METHOD','ftpext');
The issue lies in file /wp-admin/includes/class-wp-filesystem-ftpext.php. Check line 415 and 416. The new system sees the file .maintenance as a directory instead of a file, and tries to delete it by FTP_RMDIR (instead of FTP_DELETE). This results in the following error:
Got error 'PHP message: PHP Warning: ftp_rmdir(): /.maintenance: No such file or directory in /var/www/website.org/wp-admin/includes/class-wp-filesystem-ftpext.php on line 397'
For now I used a workaround and copied the old file class-wp-filesystems-ftpext.php from WP 6.03 to my WP6.1 file. This solves the issue.
My environment: Debian (bullseye), Apache + PHP 7.4.30. For FTP I'm using ProFTPD.
This ticket was mentioned in Slack in #core by jeffpaul. View the logs.
2 years ago
#12
@
2 years ago
- Keywords dev-feedback added
I've reproduced the issue using ProFTPD. After looking into this, I'm going to step through each part below.
This is a long one.
maintenance_mode() calls:
<?php $file = $wp_filesystem->abspath() . '.maintenance'; $wp_filesystem->delete( $file );
Note the signature of WP_Filesystem_FTPext::delete():
<?php public function delete( $file, $recursive = false, $type = false )
WP_Filesystem_FTPext::delete()
contains this:
<?php if ( 'f' === $type || $this->is_file( $file ) ) { return ftp_delete( $this->link, $file ); }
maintenance_mode()
doesn't pass the $type
argument, so let's focus on $this->is_file( $file )
.
WP_Filesystem_FTPext::is_file()
<?php public function is_file( $file ) { return $this->exists( $file ) && ! $this->is_dir( $file ); }
! $this->is_dir( $file )
returns true
, which is fine, so let's focus on $this->exists( $file )
.
WP_Filesystem_FTPext::exists() - 6.1
<?php public function exists( $path ) { if ( $this->is_dir( $path ) ) { return true; } return ! empty( ftp_rawlist( $this->link, $path ) ); }
Let's go ahead and skip $this->is_dir( $path )
as we know this returns false
.
On to ftp_rawlist()
...
Most FTP servers have the -a
switch enabled by default. This includes hidden files, and so for these servers, an existing .maintenance
file will return a non-empty result from ftp_rawlist()
, meaning the file exists. ✅
However, ProFTPD doesn't include this switch by default, so won't pick up the file. ❌ This will return to ::delete()
and then call rmdir()
. 💥🐞
In addition, including the switch when an FTP server already includes it can throw an error, so we can't just call ftp_rawlist( $this->link, ' -a ' . $path )
. ❗
Therefore, from what I've seen so far, we need to:
- Call
ftp_rawlist()
without the switch. This will cover:- Existing non-hidden files. ✅
- Existing hidden files on FTP servers who enable the switch by default. ✅
- If the file doesn't exist, we then call
@ftp_rawlist()
with the switch. This will cover:- Existing hidden files on FTP servers who don't enable the switch by default. ✅
- Note: The
@
operator is needed to suppress errors when$file
doesn't exist on FTP servers that enable the switch by default. I know, we're trying to reduce the usage of this operator, and I still need to reproduce the error to see if it's a fatal, as@
won't work on PHP8+ in that case.
This looks like:
<?php
public function exists( $path ) {
if ( $this->is_dir( $path ) ) {
return true;
}
if ( ! empty( ftp_rawlist( $this->link, $path ) ) ) {
return true;
}
+ /*
+ * Include '-a' switch for FTP servers that do not enable it by default.
+ *
+ * For some FTP servers that enable the switch by default, including the
+ * switch again can produce an error, so the '@' operator must be used.
+ */
+ if ( ! empty( @ftp_rawlist( $this->link, ' -a ' . $path ) ) ) {
+ return true;
+ }
return false;
}
Now, that requires confirmation of the type of error thrown, as well as discussion on whether this approach is agreeable to committers.
For those unfamiliar, the aim of #51170 was to make WP_Filesystem_FTPext::exists()
compliant with RFC 959 (CTRL+F NAME LIST (NLST)
for ftp_nlist()
- 6.0, LIST (LIST)
for ftp_rawlist()
- 6.1). The current implementation, and the above code block, are compliant with RFC 959. The implementation up to WordPress 6.0 was not.
I've tested the above code block on vsftpd, PureFTPd and ProFTPD, and it's successful on all three.
For WP_Filesystem_FTPext
, this means:
::exists()
will continue to be RFC 959 compliant.::exists()
will work with FTP servers that do/do not enable the-a
switch by default.
Adding dev-feedback
.
I also still need to find out what type of warning/error is thrown on FTP servers that already enable the switch and -a
is passed with ftp_rawlist()
. MacOS' built-in FTP server does this, so if anyone can set up WordPress to use define( 'FS_METHOD', 'ftpext' )
running the Mac FTP server, implement the above change, remove the @
operator, and call ::exists()
on a file that doesn't exist, that would be great!
This ticket was mentioned in Slack in #core-upgrade-install by costdev. View the logs.
2 years ago
This ticket was mentioned in Slack in #core by costdev. View the logs.
2 years ago
#15
@
2 years ago
For those unfamiliar, the aim of #51170 was to make WP_Filesystem_FTPext::exists() compliant with RFC 959 (CTRL+F NAME LIST (NLST) for ftp_nlist() - 6.0, LIST (LIST) for ftp_rawlist() - 6.1). The current implementation, and the above code block, are compliant with RFC 959. The implementation up to WordPress 6.0 was not.
I believe ftp_nlist()
was previously used here for a reason, because being compliant with the specs and working with all FTP servers was impossible. #28013 has some related commits where changing that exists()
method caused breakages on other servers (I believe #51170 may be a duplicate of that earlier ticket even)
Personally, I would err on the side of caution and recommend reverting the changes in #51170 from 6.1.1, perform more testing, and try again in 6.2.
If you want to retain it, and use -a
you can probably always send it, as it's used elsewhere in the class.
#16
@
2 years ago
I agree with our lead-dev, reverting is safest given the historic problems on the earlier ticket.
Commits on the earlier ticket [53860,53862,53898].
#17
@
2 years ago
Same issue here with update plugins on a FreeBSD ftp server.
The WPFileSystemFtpExt exists method relies on ftp_rawlist
Which returns 'No such file or directory' on FreeBSD.
So to result will not be empty.
#18
@
2 years ago
- Keywords needs-testing needs-patch dev-feedback removed
Agreed, [53860] should be reverted.
Always sending -a
may be problematic on some FTP servers and may also need to be changed in ::dirlist()
.
Let's investigate this further in 6.2.
This ticket was mentioned in Slack in #core by jeffpaul. View the logs.
2 years ago
#20
@
2 years ago
Personally, I would err on the side of caution and recommend reverting the changes in #51170 from 6.1.1, perform more testing, and try again in 6.2.
After looking at this and getting clarification from @dd32 on the statement above, let's do the following:
- Leave the unrelated changes to
WP_Filesystem_FTPext::size()
in [53898]. This would only have a negative impact if someone is forcing FTPext AND performing comparisons such as-1 == $ftp->size()
or0 > $ftp->size()
type comparisons. This is highly unlikely and also completely unrelated to the problematic changes. - Revert the first and third chunks of [53862]. The middle chunk was refined and corrected in [53898].
- Revert parts of [53860] unrelated to
size()
method.
This ticket was mentioned in PR #3605 on WordPress/wordpress-develop by @desrosj.
2 years ago
#21
- Keywords has-patch added
This reverts the problematic parts of https://core.trac.wordpress.org/changeset/53862 and https://core.trac.wordpress.org/changeset/53898.
Trac ticket: https://core.trac.wordpress.org/ticket/56966
#22
@
2 years ago
I've attached a PR that I think reverts the parts of [53862] and [53860] while making sure the changes made in [53872] are still present.
#23
@
2 years ago
- Keywords commit added
The linked pull requests has multiple approvals, marking for commit.
#24
@
2 years ago
- Owner set to desrosj
- Resolution set to fixed
- Status changed from new to closed
In 54815:
#26
@
2 years ago
- Keywords fixed-major added
- Resolution fixed deleted
- Status changed from closed to reopened
Reopening for backport.
This ticket was mentioned in Slack in #hosting-community by javier. View the logs.
2 years ago
#30
@
2 years ago
@boldfish Thanks for posting another instance of this issue occurring. For future research, what FTP server do you use?
Can you provide some data about your environment? Was anything missing afterwards?