moxystudio/node-proper-lockfile

Error: Lock file is already being held

marcj opened this issue · 4 comments

marcj commented

I'm using proper-lockfile in a Jest test suite which is executed in parallel across multiple processes.

My code

    import * as lockFile from 'proper-lockfile';
    import {readJsonSync, writeJSONSync} from "fs-extra";
    const startPort = 28000;
    const portFile = '/tmp/glut-integration-port.txt';

>   lockFile.lockSync(portFile, {stale: 30000});
    let port = startPort;
    try {
        port = readJsonSync(portFile, {throws: false}) || startPort;
        if (port > 50000) {
            port = startPort;
        }
        const thisPort = port + 1;
        writeJSONSync(portFile, thisPort);
    } finally {
        lockFile.unlockSync(portFile);
    }

When Jest is executed I get randomly the following error:

Error: Lock file is already being held

    at /Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/lockfile.js:68:47
    at Object.newFs.<computed> [as stat] (/Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/adapter.js:20:13)
    at /Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/lockfile.js:56:20
    at Object.newFs.<computed> [as mkdir] (/Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/adapter.js:17:24)
    at acquireLock (/Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/lockfile.js:29:16)
    at RetryOperation._fn (/Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/lockfile.js:233:13)
    at RetryOperation.Object.<anonymous>.RetryOperation.attempt (/Users/marc/bude/glut.ts/node_modules/proper-lockfile/node_modules/retry/lib/retry_operation.js:112:8)
    at /Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/lockfile.js:232:19
    at Object.newFs.<computed> [as realpath] (/Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/adapter.js:20:13)
    at resolveCanonicalPath (/Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/lockfile.js:22:16)
    at lock (/Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/lockfile.js:224:5)
    at /Users/marc/bude/glut.ts/node_modules/proper-lockfile/lib/adapter.js:53:9
    at AsyncFunction.lockSync (/Users/marc/bude/glut.ts/node_modules/proper-lockfile/index.js:13:42)

Environment:

  npm: '6.9.0',
  node: '12.2.0',
  macOS 10.15.1
dmail commented

Also happens for me during npm install in my GitHub workflows

  1. I have playwright in my devDependencies
  2. It happens when relaunching a Github workflow (not on first run) In fact it's random, when it starts to happen it happens a lot even on new commits

macOS 10.15.7
Node 16.13.0
npm 8.1.0

npm ERR! code 1
npm ERR! path /Users/runner/work/server/server/node_modules/@jsenv/core/node_modules/playwright
npm ERR! command failed
npm ERR! command sh -c node install.js
npm ERR! /Users/runner/work/server/server/node_modules/proper-lockfile/lib/lockfile.js:68
npm ERR!                 return callback(Object.assign(new Error('Lock file is already being held'), { code: 'ELOCKED', file }));
npm ERR!                                               ^
npm ERR! 
npm ERR! Error: Lock file is already being held
npm ERR!     at /Users/runner/work/server/server/node_modules/proper-lockfile/lib/lockfile.js:68:47
npm ERR!     at callback (/Users/runner/work/server/server/node_modules/graceful-fs/polyfills.js:299:20)
npm ERR!     at FSReqCallback.oncomplete (node:fs:199:5) {
npm ERR!   code: 'ELOCKED',
npm ERR!   file: '/Users/runner/Library/Caches/ms-playwright'
npm ERR! }

use pnpm iwindows10 node 16.13.0

 E:\Walker\Desktop\learn\vite\node_modules\.pnpm\proper-lockfile@4.1.2\node_modules\proper-lockfile\lib\lockfile.js:68     
│                 return callback(Object.assign(new Error('Lock file is already being held'), { code: 'ELOCKED', file }));  
│                                               ^
│ Error: Lock file is already being held
│     at E:\Walker\Desktop\learn\vite\node_modules\.pnpm\proper-lockfile@4.1.2\node_modules\proper-lockfile\lib\lockfile.j  
│     at callback (E:\Walker\Desktop\learn\vite\node_modules\.pnpm\registry.npmmirror.com+graceful-fs@4.2.8\node_modules\g  
│     at FSReqCallback.oncomplete (node:fs:199:5) {
│   code: 'ELOCKED',
│   file: 'C:\\Users\\Walker\\AppData\\Local\\ms-playwright'
│ }

I've been getting this as well, in my case I suspect it's that I'm not giving enough time for the process to try to acquire a lockfile. Originally I was allocating 10-1000ms, but now I'm extending the window:

  await lockfile.lock(dbLockfilePath, {
    retries: { retries: 100, minTimeout: 10, maxTimeout: 100 },
  });

My suspicion is that there's enough contention that it's not able to process all the work and give the lock to the one making the request within 1000ms, because Jest will max out CPU usage real hard.

This is happening for us a lot with linux (Ubuntu) users, and for the same exact code it does not seem to EVER be a problem for other operating systems.