<!--  As an open source project with a dedicated but small maintainer team, it can sometimes take a long time for issues to be addressed so please be patient and we will get back to you as soon as we can.
-->

### Preflight Checklist
<!-- Please ensure you've completed the following steps by replacing [ ] with [x]-->

* [x] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
* [x] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
* [x] I have searched the issue tracker for an issue that matches the one I want to file, without success.

### Issue Details

* **Electron Version:**
  * Any 9.x or higher with `app.allowRendererProcessReuse = true` on Windows
* **Operating System:**
  * Tested on Windows 10 and Mac OS Catalina
* **Last Known Working Electron version:**
  * Any 8.x or any 9.x with `allowRendererProcessReuse = false` or any on the Mac.

### Expected Behavior
We have a native module that we converted to N-API in the last release which shipped with ES 8.x. This native module does device access and exposes a `EventEmiter` interface to JS running in the renderer. Native code is calling `emit` on the main thread by using a [UV Async handle](http://docs.libuv.org/en/v1.x/async.html). Yes, we called [`napi_get_uv_event_loop`](https://nodejs.org/api/n-api.html#n_api_napi_get_uv_event_loop). For the sake of troubleshooting this issue I have also completely replaced the UV code with [thread safe functions](https://nodejs.org/api/n-api.html#n_api_asynchronous_thread_safe_function_calls) (with a `call_js_cb` and empty `func`) with the same results. Also for troubleshooting I have removed all code from the async worker except [debug outputs](https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-outputdebugstringa).

On ES 8.x or with `allowRendererProcessReuse = false` notification of the JS works fine and I can see from the debug outputs that the device is detected and the notification worker is called immediately.

### Actual Behavior
On ES 9.x with `allowRendererProcessReuse = true` the async worker seems to be called very inconsistently. It is usually called at least once and then stops being called entirely. I can still see from the debug output that our native module is detecting the device events and the call to `uv_async_send` returns 0 (success) however the async worker is not run any more. Sometimes it is called once more when the app exits, and on one of my colleagues' machine it got called after minutes of delay, but then stopped working again.

During all of this the UI is responsive, JS is running, I can start the JS debugger and do stuff.

### To Reproduce
Please see above. Create a `uv_async` handle and call `uv_async_send` multiple times.

I have no example code I can publish at the moment, however if needed I can try to write a minimal example.

<!--
If you provide a URL, please list the commands required to clone/setup/run your repo e.g.
```sh
$ git clone $YOUR_URL -b $BRANCH
$ npm install
$ npm start || electron .
```
-->

### Additional information
Please let me know if you need any further information.

For now we are releasing with `allowRendererProcessReuse = false` so it's not too urgent (for us). However it seems that the UV main loop stops spinning, which would be a serious issue.

I'm aware of #18397, that's one of the reasons we converted our native modules to N-API.
shell/renderer/electron_renderer_client.cc
content::RenderFrame* render_frame) const {
  if (injected_frames_.find(render_frame) == injected_frames_.end())
    return nullptr;
  v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
  auto context =
      GetContext(render_frame->GetWebFrame(), v8::Isolate::GetCurrent());
  node::Environment* env = node::Environment::GetCurrent(context);
  if (environments_.find(env) == environments_.end())
    return nullptr;
  return env;
}
}