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

Issues running multiple instances #7

Open
nivassuline opened this issue May 16, 2023 · 5 comments
Open

Issues running multiple instances #7

nivassuline opened this issue May 16, 2023 · 5 comments

Comments

@nivassuline
Copy link

When trying to launch multiple instances (nodejs files) I get

Error: Lock is not acquired/owned by you at C:\Users\username\Desktop\foldername\node_modules\proper-lockfile\lib\lockfile.js:285:43 at LOOP (node:fs:2701:14) at process.processTicksAndRejections (node:internal/process/task_queues:77:11) { code: 'ENOTACQUIRED' }

any idea why?

@Firegarden
Copy link

Having this error quite a bit myself. Any help would be appreciated. I run 10 apps at the same time and use pm2 and I get this often enough.

error [2023-05-22T06:20:52.005Z] v-4 Error: Error: Lock is not acquired/owned by you at #run (\node_modules\browser-with-fingerprints\src\plugin\index.js:63:20) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async PuppeteerFingerprintPlugin.launch (\node_modules\browser-with-fingerprints\src\plugin\index.js:74:12) at async PuppeteerFingerprintPlugin.launch (\node_modules\puppeteer-with-fingerprints\src\index.js:8:12) at async scraper (\src\scraper.js:597:23)

@dmitry200
Copy link

same problem

@Firegarden
Copy link

There is a simple work around - stop using async. When using async the main thread switches between different running instances and if those both share the same data folder then you will receive this error.

You can either run sequentially (await each browser before starting the next)

Use threads and note you should specify a separate FINGERPRINT_CWD for each worker to ensure that they have their own storage folder for fingerprints and other data

@dmitryp-rebel
Copy link

import {createPlugin} from 'puppeteer-with-fingerprints';
import puppeteer from "puppeteer";
import process from "process";

async function one(id, timeout) {
    try {
        console.log(`${id}: Launching`)
        const plugin = createPlugin({
            launch: async (options) => puppeteer.launch(options)
        });
        const browser = await plugin.launch();
        console.log(`${id}: Started`)
        await new Promise(r => setTimeout(r, timeout))
        await browser.close();
        console.log(`${id}: Done`)
    } catch (e) {
        console.log(`${id}: Error ${e.message}`)
    }

}

process.on('uncaughtException', (e) => {
    console.log(e)
})

async function main() {
    for (let i = 0; i < 5; i++) {
        await one(i, 350_000) // longer then 300000 engine lock->unlock timeout to make engine.close() happen
    }
}

main();

It happens if more than one process run with same engine folder. Seems the root of problem is suppressed exceptions in bas-remote-engine engine._lock().

_lock() {
    try {
      fs.writeFileSync(this._getLockPath(), '');
      lock.lockSync(this._getLockPath());
    } catch (error) {
      // ignore
    }
  }

It suppresses any errors raised by locker, eg. error "Lock file is already being held" if multiple processes are running. It means client.engine.lock() were not able to get lock but continues and defines client.close() on timeout that calls engine.locker.unlock() inside. in case of 2+ processes only one has lock and if any other process does not call engine for longer then close() timeout (300_000) then client.close() is really called:
https://github.com/CheshireCaat/bas-remote-node/blob/c54a4a8f0682e4d4b2031352f735c72899ac6276/src/index.js#L297

async close() {
    await Promise.all([
      this._engine.close(),
      this._socket.close(),
    ]);
    this._isStarted = false;
  }

In this case engine.close() fails and left system with isStarted is true but socket has already closed. if scripts continue it fails with "Can't send data because WebSocket is not opened." error: CheshireCaat/bas-remote-node#19

2 additional moments:

  • Actually above client.close() approach seems potentially broken. Because it has chance to bring system into inconsistent state, when isStarted is true but socket is closed because of exception in engine.close() for any reason.
  • It is not clear what the meaning of that locker in engine. Current suppress any error means we do not care about concurrency (has no any protection). In my case I updated engine.close() code with catching any error on unlock and it works without this problem with 9 processes on same engine folder. But I would offer to check if there is any meaning in this particular engine.locker at all.

related to #CheshireCaat/bas-remote-node#19

@CheshireCaat
Copy link
Owner

@dmitryp-rebel you should strictly not use one folder when working with multiple clients in any form - this has already been discussed in closed tickets, an API has also been added for configuring the working folder - you can also use environment variables:

// For the first process:
plugin.setWorkingFolder('./fd1');

// For the second process:
plugin.setWorkingFolder('./fd2');

I agree that the close method code is not completely safe - I will improve it later when I have time. But now, if you follow the rules for launching several clients in different working folders, everything should work correctly without errors.

The logic of the lock file is necessary for the correct and safe operation of the engine; its presence guarantees the functionality of the engine version management, as well as the safety of the necessary files.

If for some reason you are not satisfied with this, I will be glad to see a PR in the repositories with solving problems in a different way - now we are busy with other tasks, changing the logic may lead to new errors, and adding something new takes time. The current solution has been tested and works - the only downside is that copies of the engine take up space.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants