Closed TREVORPINKS closed 1 month ago
The internal client for communication with the engine is automatically closed after 5 minutes, until then it keeps the connection.
Unfortunately, there is currently no method that would force it to close, while you can do it manually, for example, patching this file and add an export for the client instance.
Alternatively, a simpler option is to kill the FastExecuteScript process.
I don't want to kill a process because that's hacky. and It's a bit off I can't close everything when I want to so I want to fix this.
I am trying to think of a strategy where I would still be able to pull the latest version of the package in the future (without having to re-add my custom changes again).
Here is what I did.
Change #1 - browser-with-fingerprints\src\index.d.ts Added a dispose method
export declare class FingerprintPlugin {
dispose(): Promise
Change #2 - browser-with-fingerprints\src\plugin\index.js Added a dispose method
//A. import close from connector const { setup, fetch, versions, setEngineOptions, close } = require('./connector');
//B. added dispose method to FingerprintPlugin class module.exports = class FingerprintPlugin {
async dispose() { console.log('Releasing Resources...') close(); }
Change #3 - browser-with-fingerprints\src\plugin\connector\index.js
Added this code to the bottom of the file:
exports.close = () => dispose();
async function closeClient() { if (client) { await client.close(); } }
async function dispose() { return await lock.acquire('client', async () => { closeClient(); }); }
Now I can exit right away after running. I think you should consider adding a dispose method like this to the code base.
I made the close method too (CheshireCaat/browser-with-fingerprints@7ae8cfb), but it will be released later when I update the browser version, your option is also suitable.
OK Awesome. I'll test it when you release. Just reply to me here.
The engine has been heavily rewritten, now there is no permanent connection with the engine, therefore the closing method is no longer needed.
OK - I tested, the main scenario works where it's someone clicking 'x' to close the browser or where my code closes the browser. But... When I break using CTRL-C the program doesn't exit to the terminal anymore.
Did you consider adding your 'shut down / resource release logic' on a CTRL-C? I basically had a signalListener function that would call the browser.Close() method I added.
logger.trace('Attaching SIGINT/SIGTERM listeners');
if (!process.listeners('SIGINT').includes(signalListener)) {
process.on('SIGINT', signalListener);
}
if (!process.listeners('SIGTERM').includes(signalListener)) {
process.on('SIGTERM', signalListener);
}
Can you give an example of code that will not be completed by CTRL-C?
I tested a simple code to get a fingerprint - it exit correctly (used terminal in VSCode).
There is no additional signal processing in the plugins, but now the engine process is terminated automatically upon completion of a particular request.
In other cases, I specifically used unref
on timeouts and intervals.
OK Thanks for confirming so quickly. I tested this scenario further and i learned that it was just my logger (pino) flushing to the terminal (after pressing ctrl-c and seeing the terminal). So... nothing was hanging... i just had to press enter to see my command prompt again. looks like CTRL-C is covered in your fix just fine. Thanks again.
Great, glad the problem is solved.
1.) Copy pasted sample code into a new project. ie.
Is there a work around like calling something just after browser.close()?
PART OF THE OUTPUT
TTYWRAP
(unknown stack trace)
DNSCHANNEL
(unknown stack trace)
PROCESSWRAP
node_modules\bas-remote-node\src\services\engine.js:111 - this._process = execFile( node_modules\bas-remote-node\src\services\engine.js:58 - this._runEngineProcess(port); node_modules\bas-remote-node\src\index.js:142 - await this._engine.start(port); node_modules\browser-with-fingerprints\src\plugin\connector\index.js:41 - await client.start();
PIPEWRAP
node_modules\bas-remote-node\src\services\engine.js:111 - this._process = execFile( node_modules\bas-remote-node\src\services\engine.js:58 - this._runEngineProcess(port);
PIPEWRAP
node_modules\bas-remote-node\src\services\engine.js:111 - this._process = execFile( node_modules\bas-remote-node\src\services\engine.js:58 - this._runEngineProcess(port);
PIPEWRAP
node_modules\bas-remote-node\src\services\engine.js:111 - this._process = execFile( node_modules\bas-remote-node\src\services\engine.js:58 - this._runEngineProcess(port);
TCPWRAP
node_modules\ws\lib\websocket.js:1054 - return net.connect(options); node_modules\ws\lib\websocket.js:868 - req = websocket._req = request(opts); node_modules\ws\lib\websocket.js:88 - initAsClient(this, address, protocols, options); node_modules\bas-remote-node\src\services\socket.js:27 - createWebSocket: (url) => new WebSocket(url),
FILEHANDLE
(unknown stack trace)
FILEHANDLE
(unknown stack trace)
FILEHANDLE
(unknown stack trace)
FILEHANDLE
(unknown stack trace)
SAMPLE CODE: const { plugin } = require('playwright-with-fingerprints');
// Set the service key for the plugin (you can buy it here https://bablosoft.com/directbuy/FingerprintSwitcher/2). // Leave an empty string to use the free version. plugin.setServiceKey('');
(async () => { // Get a fingerprint from the server: const fingerprint = await plugin.fetch({ tags: ['Microsoft Windows', 'Chrome'], });
// Apply fingerprint: plugin.useFingerprint(fingerprint);
// Launch the browser instance: const browser = await plugin.launch();
// The rest of the code is the same as for a standard
playwright
library: const page = await browser.newPage(); await page.goto('https://example.com');// Print the browser viewport size: console.log( 'Viewport:', await page.evaluate(() => ({ deviceScaleFactor: window.devicePixelRatio, width: document.documentElement.clientWidth, height: document.documentElement.clientHeight, })) );
await browser.close(); })();