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
{{ message }}
Repository navigation
TemporaryDirectory clean-up fails with unsearchable directories #79325
This works around the issue, but the dirfd is missing in the onerror callback.
I have this issue because my program extracts tarballs to a temporary directory for examination. I expected that TemporaryDirectory cleaned up things when it could.
What do you think? rm -rf can't remove such a directory either but this is annoying and I think Python can do better.
Seems like a related issue : bpo-26660 . Maybe TemporaryDirectory can allow an onerror argument that is passed internally to rmtree during cleanup and state the same in the documentation that TemporaryDirectory can't cleanup read-only files?
changed the title [-]TemporaryDirectory can't be cleaned up if there are unsearchable directories[/-][+]TemporaryDirectory clean-up fails with unsearchable directories[/+]on Nov 2, 2018
lilydjwg commented on Nov 3, 2018
lilydjwgmannequin
MannequinAuthor
More actions
Yes bpo-26660 is similar but not the same. On Windows it seems a read-only file cannot be deleted while on Linux a file resident in a non-searchable directory cannot be deleted.
An onerror for TemporaryDirectory will work. Also I'd like to add an optional dir_fd argument for onerror.
On Python 3.8.5 on Windows using the code from the above patch I recently got a stack overflow:
Thread 0x00002054 (most recent call first):
File "...\lib\concurrent\futures\thread.py", line 78 in _worker
File "...\lib\threading.py", line 870 in run
File "...\lib\threading.py", line 932 in _bootstrap_inner
File "...\lib\threading.py", line 890 in _bootstrap
Thread 0x00000de4 (most recent call first):
File "...\lib\concurrent\futures\thread.py", line 78 in _worker
File "...\lib\threading.py", line 870 in run
File "...\lib\threading.py", line 932 in _bootstrap_inner
File "...\lib\threading.py", line 890 in _bootstrap
Current thread 0x00004700 (most recent call first):
File "...\lib\tempfile.py", line 803 in onerror
File "...\lib\shutil.py", line 619 in _rmtree_unsafe
File "...\lib\shutil.py", line 737 in rmtree
File "...\lib\tempfile.py", line 814 in _rmtree
File "...\lib\tempfile.py", line 806 in onerror
File "...\lib\shutil.py", line 619 in _rmtree_unsafe
File "...\lib\shutil.py", line 737 in rmtree
... repeating
-------------------------------------------
In my case, the outer exc_info from rmtree is:
PermissionError(13, 'The process cannot access the file because it is being used by another process')
And the inner exception from _os.unlink(path) is:
PermissionError(13, 'Access is denied')
I would say that expected behavior in this case would be to let the 'file is in use' error raise, instead of killing the process with an SO.
Thank you Vidar! I wasn't sure about Windows, but was not able to reproduce possible failures. Your report gives a clue.
vidartf commented on Sep 22, 2020
vidartfmannequin
Mannequin
More actions
A somewhat easy repro:
Create the temporary directory, add a subdir (not sure if subdir truly necessary at this point), use os.chdir() to set the cwd to that subdir. Clean up the temp dir. The cwd should prevent the deletion because it will be "in use".
It seems to me that if path == name, then resetperms(path) and possibly a recursive call are only needed on the first call. In subsequent calls, if path == name, then we know that resetperms(path) was already called, so it shouldn't handle PermissionError. If resetperms was ineffective (e.g. in Windows, a sharing violation or custom discretionary/mandatory permissions), or if something else changed the permissions in the mean time, just give up instead of risking a RecursionError or stack overflow. For example:
Activity
lilydjwg commentedon Nov 2, 2018
If the title doesn't explain clearly, here's a demo program that will fail:
I didn't expect this, and I didn't find an easy way to handle this except not using TemporaryDirectory at all:
This works around the issue, but the dirfd is missing in the onerror callback.
I have this issue because my program extracts tarballs to a temporary directory for examination. I expected that TemporaryDirectory cleaned up things when it could.
What do you think? rm -rf can't remove such a directory either but this is annoying and I think Python can do better.
tirkarthi commentedon Nov 2, 2018
Seems like a related issue : bpo-26660 . Maybe TemporaryDirectory can allow an onerror argument that is passed internally to rmtree during cleanup and state the same in the documentation that TemporaryDirectory can't cleanup read-only files?
[-]TemporaryDirectory can't be cleaned up if there are unsearchable directories[/-][+]TemporaryDirectory clean-up fails with unsearchable directories[/+]lilydjwg commentedon Nov 3, 2018
Yes bpo-26660 is similar but not the same. On Windows it seems a read-only file cannot be deleted while on Linux a file resident in a non-searchable directory cannot be deleted.
An onerror for TemporaryDirectory will work. Also I'd like to add an optional dir_fd argument for onerror.
serhiy-storchaka commentedon Nov 3, 2018
I am working on this. Left to test on Windows and analyze possible security issues.
serhiy-storchaka commentedon May 31, 2019
New changeset e9b51c0 by Serhiy Storchaka in branch 'master':
bpo-26660, bpo-35144: Fix permission errors in TemporaryDirectory cleanup. (GH-10320)
e9b51c0
vidartf commentedon Sep 22, 2020
On Python 3.8.5 on Windows using the code from the above patch I recently got a stack overflow:
Thread 0x00002054 (most recent call first):
File "...\lib\concurrent\futures\thread.py", line 78 in _worker
File "...\lib\threading.py", line 870 in run
File "...\lib\threading.py", line 932 in _bootstrap_inner
File "...\lib\threading.py", line 890 in _bootstrap
Thread 0x00000de4 (most recent call first):
File "...\lib\concurrent\futures\thread.py", line 78 in _worker
File "...\lib\threading.py", line 870 in run
File "...\lib\threading.py", line 932 in _bootstrap_inner
File "...\lib\threading.py", line 890 in _bootstrap
Current thread 0x00004700 (most recent call first):
File "...\lib\tempfile.py", line 803 in onerror
File "...\lib\shutil.py", line 619 in _rmtree_unsafe
File "...\lib\shutil.py", line 737 in rmtree
File "...\lib\tempfile.py", line 814 in _rmtree
File "...\lib\tempfile.py", line 806 in onerror
File "...\lib\shutil.py", line 619 in _rmtree_unsafe
File "...\lib\shutil.py", line 737 in rmtree
... repeating
-------------------------------------------
In my case, the outer
exc_infofrom rmtree is:And the inner exception from
_os.unlink(path)is:I would say that expected behavior in this case would be to let the 'file is in use' error raise, instead of killing the process with an SO.
serhiy-storchaka commentedon Sep 22, 2020
Thank you Vidar! I wasn't sure about Windows, but was not able to reproduce possible failures. Your report gives a clue.
vidartf commentedon Sep 22, 2020
A somewhat easy repro:
Create the temporary directory, add a subdir (not sure if subdir truly necessary at this point), use
os.chdir()to set the cwd to that subdir. Clean up the temp dir. The cwd should prevent the deletion because it will be "in use".eryksun commentedon Sep 23, 2020
It seems to me that if
path == name, then resetperms(path) and possibly a recursive call are only needed on the first call. In subsequent calls, ifpath == name, then we know that resetperms(path) was already called, so it shouldn't handle PermissionError. If resetperms was ineffective (e.g. in Windows, a sharing violation or custom discretionary/mandatory permissions), or if something else changed the permissions in the mean time, just give up instead of risking a RecursionError or stack overflow. For example:2 remaining items
tempfile.TemporaryDirectory: fix recursion bug (seen in pythongh-79325,
pythongh-79325: Fix recursion error in TemporaryDirectory cleanup on …
serhiy-storchaka commentedon Dec 5, 2023
I implemented this idea in #112762.
gh-79325: Fix recursion error in TemporaryDirectory cleanup on Windows (
pythongh-79325: Fix recursion error in TemporaryDirectory cleanup on …
[3.11] pythongh-79325: Fix recursion error in TemporaryDirectory clea…
[3.12] gh-79325: Fix recursion error in TemporaryDirectory cleanup on…
[3.11] gh-79325: Fix recursion error in TemporaryDirectory cleanup on…
pythongh-79325: Fix recursion error in TemporaryDirectory cleanup on …
pythongh-79325: Fix recursion error in TemporaryDirectory cleanup on …