Skip to content

Native multi-threaded N-API module callback not working in ES 9.x without allowRendererProcessReuse = false on Windows #25496

@f0zi

Description

@f0zi

Preflight Checklist

  • I have read the Contributing Guidelines for this project.
  • I agree to follow the Code of Conduct that this project adheres to.
  • 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. Yes, we called napi_get_uv_event_loop. For the sake of troubleshooting this issue I have also completely replaced the UV code with thread safe functions (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.

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.

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions