Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async dialog API is slow to return on Linux #20533

Closed
3 tasks done
oNaiPs opened this issue Oct 11, 2019 · 9 comments
Closed
3 tasks done

Async dialog API is slow to return on Linux #20533

oNaiPs opened this issue Oct 11, 2019 · 9 comments

Comments

@oNaiPs
Copy link

oNaiPs commented Oct 11, 2019

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

When using async dialog API, the function takes several seconds to return.
This can be observed in showSaveDialog, showMessageBox and showOpenDialog.

  • Electron Version:
    v7.0.0-beta.6
    v6.0.12
  • Operating System:
    Ubuntu 19.04 x64
  • Last Known Working Electron version:
    v5.0.11

Expected Behavior

There shouldn't be any added delay after user clicks on the dialog.

Actual Behavior

API only returns after several seconds after user clicked on a dialog option.

To Reproduce

Run the example code:

const { app, dialog } = require('electron');

app.on('ready', () => {
  (async () => {
    console.log('Before Dialog!');
    const res = await dialog.showMessageBox({
      buttons: [
        'ok',
      ],
      title: 'Title',
      message: 'This is a message.',
    });

    console.log('After Dialog');
    console.log(`Res: ${ JSON.stringify(res) }`);
  })().catch(e => { console.error(e); });
});

Observe the delay after clicking on "OK".

Screenshots

Bug reproduction screencast:
https://youtu.be/ZfiobQDvbOs

@lorenzogrv
Copy link

lorenzogrv commented Mar 5, 2020

After I noticed this today, and found this issue, I would like to confirm this bug for version 8.x. Note the synchronous version returns way faster than asynchronous one:

Test script:

$ cat test-slow-dialog.js 
const { app, dialog } = require('electron');

app.on('ready', () => {
  console.log('Before Dialog!');
  let box = {
    buttons: [ 'ok' ],
    title: 'Title',
    message: 'This is a message.'
  }
  let now = Date.now()
  dialog
    .showMessageBox(box)
    .then(res => {
      console.log('After promised dialog (%s ms)', Date.now() - now)
      console.log(`Res: ${ JSON.stringify(res) }`)
      return Date.now()
    })
    .then(now => {
      let res = dialog.showMessageBoxSync(box)
      console.log('After synchronous dialog (%s ms)', Date.now() - now)
      console.log(`Res: ${ JSON.stringify(res) }`)
    })
    .catch(e => console.error(e))
    .finally(() => app.quit())
});

Running the test:

$ electron test-slow-dialog.js 
Before Dialog!
After promised dialog (8041 ms)
Res: {"response":0,"checkboxChecked":false}
After synchronous dialog (806 ms)
Res: 0

Env:

$ electron --version
v8.0.2
$ uname -srv
Linux 5.5.6-genuine #1 SMP Wed Feb 26 03:38:43 CET 2020

@m4heshd
Copy link

m4heshd commented Mar 6, 2021

Can confirm this issue on Windows too. Electron v12.0.0. It takes about 3 seconds for the promise to be returned. Sync version has no issue. I don't have this issue on messagebox though.

@nornagon
Copy link
Member

I can't reproduce this on Windows under Electron v12.0.0:

Before Dialog!
After promised dialog (413 ms)
Res: {"response":0,"checkboxChecked":false}
After synchronous dialog (209 ms)
Res: 0

@nornagon
Copy link
Member

I can reproduce it on Linux, though not consistently:

Before Dialog!
Gtk-Message: 15:37:22.921: GtkDialog mapped without a transient parent. This is discouraged.
libva error: va_getDriverName() failed with unknown libva error,driver_name=(null)
After promised dialog (4994 ms)
Res: {"response":0,"checkboxChecked":false}
Gtk-Message: 15:37:27.902: GtkDialog mapped without a transient parent. This is discouraged.
After synchronous dialog (821 ms)
Res: 0

having a setInterval running in the background "patches over" this issue, which makes me think it's an event-loop integration problem.

workaround:

const { app, dialog } = require('electron');

app.on('ready', () => {
  console.log('Before Dialog!');
  let interval = setInterval(() => { /* nothing */ }, 100)
  let box = {
    buttons: [ 'ok' ],
    title: 'Title',
    message: 'This is a message.'
  }
  let now = Date.now()
  dialog
    .showMessageBox(box)
    .then(res => {
      clearInterval(interval)
      console.log('After promised dialog (%s ms)', Date.now() - now)
      console.log(`Res: ${ JSON.stringify(res) }`)
      return Date.now()
    })
    .then(now => {
      let res = dialog.showMessageBoxSync(box)
      console.log('After synchronous dialog (%s ms)', Date.now() - now)
      console.log(`Res: ${ JSON.stringify(res) }`)
    })
    .catch(e => console.error(e))
    .finally(() => app.quit())
});

@m4heshd
Copy link

m4heshd commented Mar 16, 2021

@nornagon as you said It's not consistent on Windows either. Works fine after a reboot most of the time. What I noticed is it's something related to Windows explorer because explorer sometimes crash or act buggy when I try this. Also the issue is only present for me on open/save dialogs. Probably caused by a Windows update. Async dialog API runs on a separate thread right? So under the hood it's still sync?

@lorenzogrv
Copy link

lorenzogrv commented Aug 4, 2021

@nornagon I suspect your conclusion - event loop problem - is right. I would test also something like

setImmediate(() => {
  dialog
    .showMessageBox(box)
    // ....
})

to research even more on the subject

@Uninen
Copy link

Uninen commented Feb 15, 2022

I bumped into a related issue today. I'm inexperienced with Electron so it took me quite a while to figure out what's going on. But my problem went away after applying the interval workaround so I'm assuming it's related.

I'm calling dialog.showOpenDialog in main process from the render process via a contextBridge api. In the handler I'm resolving the dialog promise and then sending result.filePaths back to the render process via another contextBridge api. This all works great -- but only once or twice.

After one or two repeated dialog opens, the render process just hangs. There's no error messages in the console and the devtools keep working, but the window freezes. The last time the dialog closes, the results are sent okay but they never arrive and the render window freezes.

After finding this ticket, I tried adding no-op setInterval to the main process handler like in the workaround above -- and now my code works as it should.

I'm running the latest Electron (17) on macOS 12.2.1.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 8, 2022

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. If you have any new additional information—in particular, if this is still reproducible in the latest version of Electron or in the beta—please include it with your comment!

@github-actions github-actions bot added the stale label Oct 8, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Nov 8, 2022

This issue has been closed due to inactivity, and will not be monitored. If this is a bug and you can reproduce this issue on a supported version of Electron please open a new issue and include instructions for reproducing the issue.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Nov 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants