Closed
Labels
3.10 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
| BPO | 35144 |
|---|---|
| Nosy | @lilydjwg, @serhiy-storchaka, @eryksun, @vidartf, @tirkarthi |
| PRs |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = 'https://github.com/serhiy-storchaka'
closed_at = None
created_at = <Date 2018-11-02.08:40:08.637>
labels = ['3.8', 'type-bug', 'library', '3.9', '3.10']
title = 'TemporaryDirectory clean-up fails with unsearchable directories'
updated_at = <Date 2021-03-28.07:31:28.296>
user = 'https://github.com/lilydjwg'bugs.python.org fields:
activity = <Date 2021-03-28.07:31:28.296>
actor = 'eryksun'
assignee = 'serhiy.storchaka'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2018-11-02.08:40:08.637>
creator = 'lilydjwg'
dependencies = []
files = []
hgrepos = []
issue_num = 35144
keywords = ['patch']
message_count = 9.0
messages = ['329116', '329127', '329184', '329185', '344036', '377309', '377316', '377329', '377358']
nosy_count = 5.0
nosy_names = ['lilydjwg', 'serhiy.storchaka', 'eryksun', 'vidartf', 'xtreak']
pr_nums = ['10320']
priority = 'normal'
resolution = None
stage = 'patch review'
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue35144'
versions = ['Python 3.8', 'Python 3.9', 'Python 3.10']Linked PRs
Metadata
Metadata
Assignees
Labels
3.10 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Projects
- StatusShow more project fieldsDone
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:8 remaining items
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 …
[3.11] pythongh-79325: Fix recursion error in TemporaryDirectory clea…
[3.10] pythongh-157579: Fix race condition in the cleanup of tempfile…
Update version to 3.10.22.2 and add release notes
[3.11] pythongh-79325: Fix recursion error in TemporaryDirectory clea…
[3.9] pythongh-157579: Fix race condition in the cleanup of tempfile.…
Update version to 3.9.25.2 and add release notes