Repository: napari/napari

Issue:
Napari bundle app crashes
## 🐛 Bug

Napari just shows a message stating "App has crashed" and starts open applications like crazy until killing all of them and it stops by killing Naparis

## To Reproduce

Steps to reproduce the behavior:

1. Open napari
2. Click on Plugins -> Install/Uninstall Package(s)..
3. Install plugins and uninstall them until app crashes


## Expected behavior

App should not crash

## Actual results

Napari starts acting like crazy opening Naparis endlessly. I need to uninstall to use it again as as soon as I want to open it, party starts all over again

## Environment
MacOS Big Sur 11.6 -  napari 0.4.11rc4

This is also reproducible in napari 0.4.11

<img width="1714" alt="Screen Shot 2021-09-24 at 11 50 41 AM" src="https://user-images.githubusercontent.com/63799148/134734701-e1e476b9-20a5-4135-a398-fa0986994ecb.png">





Discussion:
Wow! :grimacing: That is so terrible! :joy: I know @goanpeca and @jaimergp are hard at work on rearchitecting how the bundle even works, so hopefully this will disappear altogether when that effort is done.
I think I have an idea of what is going on :-p

Working on this!
Ok I started looking into this but, I do not think it is related to the plugin dialog, if I download the latest nightly build and install napari, and then open it, and wait, it will start opening multiple napari's over and over again.

I am not sure what is going on, could it be a briefcase issue?

@jaimergp, @tlambert03 any ideas?

could this be related to `def _run_pythonw(python_path):` doing something funky?


----

@lauramarcos could you try using the latest napari builds (https://github.com/napari/napari/releases/tag/latest) and just open it and wait?
yep there's definitely something going terribly wrong at the moment.  mine immediately crashes and starts a continual loop of crashing with this error message:

<img width="912" alt="Untitled 2" src="https://user-images.githubusercontent.com/1609449/136078564-e792c8c8-521e-4b06-8fb3-a3fd85393641.png">

if you put a `sys.argv` print statement in `__main__`, you can see that something is trying to start another process with the command:

```
napari -O -B -c from multiprocessing.resource_tracker import main;main(32)
```

you're getting the "no plugin capable" error because napari thinks someone is trying to open the file named "from multiprocessing.resourc..."

```
2021-10-05 14:12:38.783 napari[19234:2125292] ['napari']
2021-10-05 14:12:38.803 napari[19234:2125292] /Applications/napari.app/Contents/Resources/app/napari/__main__.py:423: UserWarning: pythonw executable not found.
2021-10-05 14:12:38.803 napari[19234:2125292] To unfreeze the menubar on macOS, click away from napari to another app, then reactivate napari. To avoid this problem, please install python.app in conda using:
2021-10-05 14:12:38.803 napari[19234:2125292] conda install -c conda-forge python.app
2021-10-05 14:12:38.803 napari[19234:2125292]   warnings.warn(msg)
2021-10-05 14:12:44.534 napari[19237:2125571] ['napari', '-O', '-B', '-c', 'from multiprocessing.resource_tracker import main;main(31)']
2021-10-05 14:12:44.558 napari[19237:2125571] /Applications/napari.app/Contents/Resources/app/napari/__main__.py:423: UserWarning: pythonw executable not found.
2021-10-05 14:12:44.558 napari[19237:2125571] To unfreeze the menubar on macOS, click away from napari to another app, then reactivate napari. To avoid this problem, please install python.app in conda using:
2021-10-05 14:12:44.558 napari[19237:2125571] conda install -c conda-forge python.app
2021-10-05 14:12:44.558 napari[19237:2125571]   warnings.warn(msg)
2021-10-05 14:12:50.256 napari[19240:2125877] ['napari', '-O', '-B', '-c', 'from multiprocessing.resource_tracker import main;main(32)']
2021-10-05 14:12:50.276 napari[19240:2125877] /Applications/napari.app/Contents/Resources/app/napari/__main__.py:423: UserWarning: pythonw executable not found.
2021-10-05 14:12:50.276 napari[19240:2125877] To unfreeze the menubar on macOS, click away from napari to another app, then reactivate napari. To avoid this problem, please install python.app in conda using:
2021-10-05 14:12:50.277 napari[19240:2125877] conda install -c conda-forge python.app
2021-10-05 14:12:50.277 napari[19240:2125877]   warnings.warn(msg)
[1]    19234 terminated  /Applications/napari.app/Contents/MacOS/napari

```

however, it's still not clear to me what's causing that second process to start
Pinging @freakboy3742, do you think this is something related to briefcase?

We are not sure where the `-O -B -c from multiprocessing.resource_tracker import main;main(32)` is coming from :-| 

@goanpeca It's quite possibly related to briefcase, but the `-O...` bit itself isn't Briefcase's work directly. 

Briefcase (and the app stub) won't be trying to launch any subprocesses. However, if you try to invoke `spawn()`, that call will fail because `sys.executable` will be the executable of the briefcase stub app, which doesn't (currently) process the command line passed in as part of a `spawn()` call. If you've got code that is invoking multiprocessing, that may be invoking `spawn()` implicitly, as spawn is the default mode for multiprocessing as of Python 3.8.

You may have more luck if you use `forkserver` mode; `fork` may also be an option, with the caveats [mentioned in the docs](https://docs.python.org/3.8/library/multiprocessing.html#contexts-and-start-methods). 

Longer term - we need to modify the Briefcase stub binary and/or patch multiprocessing to account for `spawn()`.

`pyinstaller` issue tracker has this one: https://github.com/pyinstaller/pyinstaller/issues/4865

One specific [comment](https://github.com/pyinstaller/pyinstaller/issues/4865#issuecomment-680327611) here is very useful:

> On macOS 3.8 the default start method for multiprocessing is spawn. On macOS 3.7 it was fork.

(see source [here](url))

Since we updated our Python to support newer MacOS in #2991, we are now using `spawn` by default.

Apparently, this can be fixed (at least in `pyinstaller`) with this [construct](https://github.com/pyinstaller/pyinstaller/issues/4865#issuecomment-699603931):

```python
multiprocessing.freeze_support()
multiprocessing.set_start_method('spawn')
```

Resolving patch:
diff --git a/napari/__main__.py b/napari/__main__.py
--- a/napari/__main__.py
+++ b/napari/__main__.py
@@ -421,6 +421,13 @@ def main():
                 'conda install -c conda-forge python.app'
             )
             warnings.warn(msg)
+
+    # Prevent https://github.com/napari/napari/issues/3415
+    if sys.platform == "darwin" and sys.version_info >= (3, 8):
+        import multiprocessing
+
+        multiprocessing.set_start_method('fork')
+
     _run()
 
 


Test patch: