Repository: qutebrowser/qutebrowser

Issue:
FileNotFoundError with fileselect file
https://crashes.qutebrowser.org/view/2b4a85eb

```
20:03:45 DEBUG    procs      guiprocess:_pre_start:154 Executing: kitty nnn -p /tmp/qutebrowser-fileselect-kqiigxcd
[...]
20:03:48 DEBUG    procs      guiprocess:_on_finished:91 Process finished with code 0, status 0.
20:03:48 ERROR    misc       utils:cleanup_file:891 Failed to delete tempfile /tmp/qutebrowser-fileselect-kqiigxcd ([Errno 2] No such file or directory: '/tmp/qutebrowser-fileselect-kqiigxcd')!
20:03:48 ERROR    misc       crashsignal:_handle_early_exits:240 Uncaught exception
Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/qutebrowser/browser/webengine/webview.py", line 255, in chooseFiles
    return shared.choose_file(
  File "/usr/lib/python3.9/site-packages/qutebrowser/browser/shared.py", line 375, in choose_file
    with open(tmpfilename, mode='r', encoding=sys.getfilesystemencoding()) as f:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/qutebrowser-fileselect-kqiigxcd'
```

Not sure how they managed to (probably accidentally?) delete that file via `nnn`, but we should probably handle `OSError` in general there (which includes `FileNotFoundError`.

@AckslD Is this something you want to take a look at?


Discussion:
Ah, no, we don't create the file at all - we just blindly assume it exists. Thus, if the terminal window with `nnn` gets closed (probably with `vifm` / `ranger` as well, but I didn't check), then the exception will happen.
@The-Compiler Sure thing, I'll open a PR tomorrow :+1:

Resolving patch:
diff --git a/qutebrowser/browser/shared.py b/qutebrowser/browser/shared.py
--- a/qutebrowser/browser/shared.py
+++ b/qutebrowser/browser/shared.py
@@ -372,8 +372,12 @@ def choose_file(multiple: bool) -> List[str]:
         proc.finished.connect(lambda _code, _status: loop.exit())
         loop.exec()
 
-        with open(tmpfilename, mode='r', encoding=sys.getfilesystemencoding()) as f:
-            selected_files = f.read().splitlines()
+        try:
+            with open(tmpfilename, mode='r', encoding=sys.getfilesystemencoding()) as f:
+                selected_files = f.read().splitlines()
+        except OSError as e:
+            message.error(f"Failed to open tempfile {tmpfilename} ({e})!")
+            selected_files = []
 
     if not multiple:
         if len(selected_files) > 1:


Test patch:
diff --git a/tests/end2end/features/editor.feature b/tests/end2end/features/editor.feature
--- a/tests/end2end/features/editor.feature
+++ b/tests/end2end/features/editor.feature
@@ -219,3 +219,14 @@ Feature: Opening external editors
         And I open data/fileselect.html
         And I run :click-element id multiple_files
         Then the javascript message "Files: 1.txt, 2.txt" should be logged
+
+    ## No temporary file created
+
+    Scenario: File selector deleting temporary file
+        When I set fileselect.handler to external
+        And I set fileselect.single_file.command to ['rm', '{}']
+        And I open data/fileselect.html
+        And I run :click-element id single_file
+        Then the javascript message "Files: 1.txt" should not be logged
+        And the error "Failed to open tempfile *" should be shown
+        And "Failed to delete tempfile *" should be logged with level error