electron / electron

:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS
https://electronjs.org
MIT License
114.19k stars 15.4k forks source link

[Bug]: printToPDF freeze / stuck the app (is not responding) #31695

Closed gaetandezeiraud closed 2 years ago

gaetandezeiraud commented 2 years ago

Preflight Checklist

Electron Version

15.3.0

What operating system are you using?

Windows

Operating System Version

Windows 11 22000.282

What arch are you using?

x64

Last Known Working Electron version

No response

Expected Behavior

Generate the PDF in the background and don't stuck the main window of the application.

Actual Behavior

During the generation of the PDF. The main window not respond and Windows show "is not responding" in the Task Manager. Can't interact with the content of the app or move it.

Testcase Gist URL

No response

Additional Information

I have trying to run the printToPDF on a node worker or fork processus. Without success. My renderer don't wait any answer from the main. After a couple of seconds, when the pdf is generated, the app work correctly.

// Print to PDF
ipcMain.on('generatePDF', (event, name, type, id) => {
  const pdfOptions = {
    marginsType: 1,
    pageSize: 'A4',
    printBackground: true,
    printSelectionOnly: false,
    landscape: false
  };

  let win = new BrowserWindow({
    show: false,
    webPreferences: {
      preload: PDF_WINDOW_PRELOAD_WEBPACK_ENTRY,
    }
  });

  win.loadURL(PDF_WINDOW_WEBPACK_ENTRY + `?${new URLSearchParams({id, type})}`);

  const filePath = dialog.showSaveDialogSync(mainWindow, {
    defaultPath: name,
    filters: [
      { name: 'PDF', extensions: ['pdf'] }
    ]
  });

  event.sender.send('onPDFStartResponse');

  if (filePath && filePath.length > 0) {
    win.webContents.on('did-finish-load', () => {
      win.webContents.printToPDF(pdfOptions).then(data => {
        fs.writeFile(filePath, data, function (err) {
          if (err) {
            log.error(err);
          } else {
            log.info('PDF Generated Successfully');
            event.sender.send('onPDFGeneratedResponse', path.basename(filePath));
          }

          win.close();
          win = null;
          // shell.openExternal(filePath);
        });
      }).catch(error => {
        log.error(error)
        win.close();
        win = null;
      });
    });
  } else {
    win.close();
    win = null;
  }
});

Inside my preload:

import { ipcRenderer, contextBridge } from 'electron';

contextBridge.exposeInMainWorld('electron', {
    generatePDF: (name, type, id) => ipcRenderer.send('generatePDF', name, type, id),
});

Inside my app: window.electron.generatePDF(Devis-${this.estimate.id.toString().padStart(6, 0)}.pdf, 'estimate', this.estimate.id);

gaetandezeiraud commented 2 years ago

Maybe related https://github.com/electron/electron/issues/17171 (but I don't use await)

codebytere commented 2 years ago

Thanks for reporting this and helping to make Electron better!

Because of time constraints, triaging code with third-party dependencies is usually not feasible for a small team like Electron's.

Would it be possible for you to make a standalone testcase with only the code necessary to reproduce the issue? For example, Electron Fiddle is a great tool for making small test cases and makes it easy to publish your test case to a gist that Electron maintainers can use.

Stand-alone test cases make fixing issues go more smoothly: it ensure everyone's looking at the same issue, it removes all unnecessary variables from the equation, and it can also provide the basis for automated regression tests.

I'm adding the blocked/need-repro label for this reason. After you make a test case, please link to it in a followup comment. This issue will be closed in 10 days if the above is not addressed.