|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2021-07-14 22:45 UTC] raincomplain at outlook dot com
Description:
------------
As you know on Windows as of PHP 7.3 it is possible to unlink() files with handles in use (no need to close the handle). To do that it seems to me that PHP trys to (delay) unlinking until program execution ends(which is the problem). Unlinking files in the past when a file handle is open was not possible at all, however as of 7.3 unlink() returns `true` even though the file is not deleted yet.
The test script shows that we can do things (creating data2.txt) even when the program is not correct yet (data.txt has to wait 10 seconds to be removed).
Test script:
---------------
$fp= fopen('data.txt', 'r');
if (unlink('data.txt')) {
fopen('data2.txt', 'w');
}
sleep(10);
Expected result:
----------------
.
..
data2.txt
Actual result:
--------------
.
..
data.txt
data2.txt ( for 10 seconds)
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 22:00:01 2025 UTC |
The respective changes in PHP 7.3 are an attempt to more closely match POSIX semantics regarding unlinking of files. On Windows, unlinking is not possible if there are open file handles, so putting the file in a delete-pending state is the closest equivalent, and that means that the file will be deleted after the last handle to it has been closed, and it is no longer possible to access the file in any way (permission denied). It seems to me that under this semantics having unkink() returning true is actually correct – this still allows to check whether the file was put in delete-pending state or not. However, files in delete-pending state behave pretty inconsistently wrt. other file functions; while file_exist() and friends return false, scandir() and friends still report the file to be there. If we were putting the file in delete-on-close state, the results of these functions would be consistent (file_exist() and friends would return true), but even if it is possible to implement that, the file will eventually move to the delete-pending state, and the inconsistency would show up again. I'm not sure what to do here. unlink()ing by putting the file in the delete-pending state appears generally more useful than just letting the unlink() attempt fail, so we likely will not revert this (besides that it is a bit late; PHP 7.3.0 was released more than 30 months ago). Fixing the inconsistencies between file_exists() and scandir() is likely not possible (or worth the trouble). So it might be best to clearly document the exact behavior. Still, it seems to me there is no (clean) way to detect whether a file is in delete-pending state, and at least that appears to be an unfortunate omission. If such a function was available, userland code could do something like if (unlink('data.txt') && !file_is_delete_pending('data.txt)) { fopen('data2.txt', 'w'); } From what I can tell, writing such a function in C should be possible and not too hard. Further reading: <https://go.microsoft.com/fwlink/?LinkId=140636> (particularly chapter 4, File deletion semantics).