Repository: nilearn/nilearn

Issue:
Seemingly random test failure with `test_temp_file_removing`
There is a test that checks if a temporary file was removed correctly and it seems to fail randomly every once in a while. I am looking into it to see if I can improve the test. 
See [test here](https://github.com/nilearn/nilearn/blob/main/nilearn/plotting/tests/test_html_document.py)
See [failure here](https://dev.azure.com/Parietal/Nilearn/_build/results?buildId=4733&view=logs&j=8d5ac5f6-e89e-50f1-f198-d1a0983ad562&t=73659071-ebed-5a28-0af2-8b5a9c385fe0&l=11372)


Discussion:
No clue about that. Maybe find related issues on internet.
one first thing we could try is augment the `time.sleep(1.5)` to something a bit larger
Indeed giving more room would help deal with inaccuracies in the timing. Another potential solution is to replace the  `time.sleep(1.5)` line with `os.wait()` so that the process waits for the subprocess to finish before moving to the next line. WDYT? Any downsides?
That's a good idea! the doc says `os.wait` is only available on unix. we could have `open_in_browser` return the process id of the process that removes the temp file, or store it as an attribute of the HTMLDocument (in the same way it has the `_temp_file` attribute), and use `os.waitpid`? for debugging and testing purposes rather than just the pid we may also want to hold onto the whole `Popen` object created in `_remove_after_n_seconds`
> for debugging and testing purposes rather than just the pid we may also want to hold onto the whole `Popen` object created in `_remove_after_n_seconds`

in that case we could also use `Popen.wait` (and set a timeout)
I am not sure how we can use `Popen.wait` here because as I understood it is usually used for the opposite of what I think we want to do here: it waits for the process to finish before continuing the subprocess which is useful when the subprocess relies on a return from the process. 

And good point about `os.wait`. I think using `os.waitpid` instead should work fine. I can open a PR to implement that and we can work from there.

Resolving patch:
diff --git a/nilearn/plotting/html_document.py b/nilearn/plotting/html_document.py
--- a/nilearn/plotting/html_document.py
+++ b/nilearn/plotting/html_document.py
@@ -21,7 +21,9 @@ def set_max_img_views_before_warning(new_value):
 
 def _remove_after_n_seconds(file_name, n_seconds):
     script = os.path.join(os.path.dirname(__file__), 'rm_file.py')
-    subprocess.Popen([sys.executable, script, file_name, str(n_seconds)])
+    proc = subprocess.Popen([sys.executable, script, file_name,
+                             str(n_seconds)])
+    return proc
 
 
 class HTMLDocument(object):
@@ -44,6 +46,7 @@ def __init__(self, html, width=600, height=400):
         self.height = height
         self._temp_file = None
         self._check_n_open()
+        self._temp_file_removing_proc = None
 
     def _check_n_open(self):
         HTMLDocument._all_open_html_repr.add(self)
@@ -161,7 +164,8 @@ def open_in_browser(self, file_name=None, temp_file_lifetime=30):
                      "for example by calling this.remove_temp_file").format(
                          file_name, file_size))
         else:
-            _remove_after_n_seconds(self._temp_file, temp_file_lifetime)
+            self._temp_file_removing_proc = _remove_after_n_seconds(
+                self._temp_file, temp_file_lifetime)
         webbrowser.open('file://{}'.format(file_name))
 
     def remove_temp_file(self):


Test patch:
diff --git a/nilearn/plotting/tests/test_html_document.py b/nilearn/plotting/tests/test_html_document.py
--- a/nilearn/plotting/tests/test_html_document.py
+++ b/nilearn/plotting/tests/test_html_document.py
@@ -29,7 +29,7 @@ def test_temp_file_removing():
             assert "Saved HTML in temporary file" not in str(warning.message)
         html.open_in_browser(temp_file_lifetime=0.5)
         assert os.path.isfile(html._temp_file)
-        time.sleep(1.5)
+        html._temp_file_removing_proc.wait()
         assert not os.path.isfile(html._temp_file)
         with pytest.warns(UserWarning, match="Saved HTML in temporary file"):
             html.open_in_browser(temp_file_lifetime=None)