prerender: Timed out waiting for Chrome connection after Restarting Chrome

Running prerender in a docker container, after a period of time, all requests Timed out waiting for Chrome connection will appear. After observation, I found that most of them appear after Restarting Chrome. I try to set BROWSER_TRY_RESTART_PERIOD time This problem will appear faster after being shortened. It is speculated that the source of the problem is a problem with the steps to reset Chrome

Version:

$ node server.js
2023-07-03T05:28:50.172Z Starting Prerender
2023-07-03T05:28:50.175Z Starting Chrome
2023-07-03T05:28:50.193Z Prerender server accepting requests on port 3000
2023-07-03T05:28:50.713Z Started Chrome: HeadlessChrome/114.0.5735.198

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 3
  • Comments: 16

Most upvoted comments

We should find a proper solution for the main issue btw. I am still investigating.

I am trying a workaround by adding the code below:

this.startPrerender();

at the end of server.restartBrowser function in ./lib/server.js:143 to force the restart.

which will be like:

server.restartBrowser = function () {
	this.isBrowserConnected = false;
	util.log(`Restarting ${this.browser.name}`);
	this.browser.kill();
	this.startPrerender(); //<--- This will be added
};

I believe there is an issue with latest chrome versions which causes error on prerender to listen chromeChild.on('close', callback) event and that locks the whole process. That’s why triggering the start function without listening close event seems to solve it.

I am not sure if it will cause any memory leak but it is working for now, at least.

Disable browserForceRestart plugin also from server.js on root which relies on close event and probably causing error.

// server.use(prerender.browserForceRestart());

UPDATE:

No chance 😦 Memory leak as I guessed. Trying to install older Chrome version that I got from the container @jirikrepl shared.

Here on GitHub, there are several created issues with 504 errors.

I tried to read the Chrome log file, but there’s nothing when a 504 error happens. I also don’t think is somehow related to server resources CPU, and RAM. I tried to scale the Ubuntu server in the Digital Ocean droplet to the max and got the same 504 error. I also don’t think this is the issue https://github.com/prerender/prerender/pull/748 For me, both versions do not work.

I think it might be somehow related either to the OS (e.g. Ubuntu Server on digital ocean), or Chrome itself, when it crashes with a 504 error.

On the same Ubuntu server droplet, I tried to run this container: This container works really well, and I am probably going to use it in production. https://hub.docker.com/r/tvanro/prerender-alpine https://github.com/tvanro/prerender-alpine

This docker image has older Chrome inside. I checked prerender server diff here on Github, and it seems there are no major changes (I mean prerender server in the docker image compared with the latest code here).

I suspect the 504 error might be somehow related to newer Chrome, OS, or some environment configuration. I tried to run prerender server on MacOS, without issue.

views?

@nijinekoyo I followed this solution and it worked for me https://github.com/prerender/prerender/issues/755 I reverted back this change. https://github.com/prerender/prerender/pull/748/files Give it a try!

Is there any update for this? Facing the same issue

Same issue… confirmed on Mac M2 with Chrome 114

Hi guys,

I faced the same problem. I have for this problem a quick and dirty workaround.👯

create a new file e.q monitor.js and copy paste this:

const { spawn } = require(‘child_process’);

let yourCommand;

function startAndMonitorProcess() { if (yourCommand) { yourCommand.stdout.removeAllListeners(‘data’); yourCommand.stderr.removeAllListeners(‘data’); yourCommand.kill(); }

yourCommand = spawn(‘node’, [‘server.js’]);

yourCommand.stdout.on(‘data’, (data) => { console.log(stdout: ${data}); if (data.includes(‘Timed out waiting for Chrome connection’)) { console.log(“Error detected! Restarting…”); startAndMonitorProcess(); } });

yourCommand.stderr.on(‘data’, (data) => { console.error(stderr: ${data}); });

yourCommand.on(‘close’, (code) => { console.log(child process exited with code ${code}); }); }

startAndMonitorProcess();

this will check the output of server.js if the problem is listed in the console - this script will kill the instance and create a new server.js instance and begins from begin to listen the output.

Great I’ve made some additions to put some pm2 magic in it. you can save it as pm2_monitor.js and run it also by using pm2 like pm2 start pm2_monitor.js

const { spawn, exec } = require('child_process');
const pm2 = require('pm2')

let yourCommand;

function pm2Start() {
    if (yourCommand) {
        exec('pkill chrome');
        yourCommand.stdout.removeAllListeners('data');
        yourCommand.kill();
        pm2.disconnect();
    }
    pm2.connect(function (err) {
        if (err) {
            console.error(err)
            process.exit(2)
        }
        pm2.start({
            script: 'server.js',
            name: 'server',
            instances: 7
        }, function (err, apps) {
            if (err) {
                console.error(err)
                return pm2.disconnect()
            }

            yourCommand = spawn('pm2', ['log']);
            yourCommand.stdout.on('data', (data) => {
                if (data.includes('page timed out') || data.includes('parse html timed out') || data.includes('Timed out waiting for')) {
                    console.log("Error detected! Restarting...");
                    pm2.kill(function () {
                        pm2Start();
                    });
                }
            });
        })
    });
}
pm2Start();

Hi guys,

I faced the same problem. I have for this problem a quick and dirty workaround.👯

create a new file e.q monitor.js and copy paste this:

const { spawn } = require(‘child_process’);

let yourCommand;

function startAndMonitorProcess() { if (yourCommand) { yourCommand.stdout.removeAllListeners(‘data’); yourCommand.stderr.removeAllListeners(‘data’); yourCommand.kill(); }

yourCommand = spawn(‘node’, [‘server.js’]);

yourCommand.stdout.on(‘data’, (data) => { console.log(stdout: ${data}); if (data.includes(‘Timed out waiting for Chrome connection’)) { console.log(“Error detected! Restarting…”); startAndMonitorProcess(); } });

yourCommand.stderr.on(‘data’, (data) => { console.error(stderr: ${data}); });

yourCommand.on(‘close’, (code) => { console.log(child process exited with code ${code}); }); }

startAndMonitorProcess();

this will check the output of server.js if the problem is listed in the console - this script will kill the instance and create a new server.js instance and begins from begin to listen the output.

I am trying a workaround by adding the code below:

this.startPrerender();

at the end of server.restartBrowser function in ./lib/server.js:143 to force the restart.

which will be like:

server.restartBrowser = function () {
	this.isBrowserConnected = false;
	util.log(`Restarting ${this.browser.name}`);
	this.browser.kill();
	this.startPrerender(); //<--- This will be added
};

I believe there is an issue with latest chrome versions which causes error on prerender to listen chromeChild.on('close', callback) event and that locks the whole process. That’s why triggering the start function without listening close event seems to solve it.

I am not sure if it will cause any memory leak but it is working for now, at least.

Disable browserForceRestart plugin also from server.js on root which relies on close event and probably causing error.

// server.use(prerender.browserForceRestart());

UPDATE:

No chance 😦 Memory leak as I guessed. Trying to install older Chrome version that I got from the container @jirikrepl shared.

None of the approaches I tried have worked yet. Even tried chromium versions instead of chrome-stable but no chance. Considering permission issues now.