(lockPath: string)
| 192 | * once; if reclaim also fails the caller waits and retries via state re-read. |
| 193 | */ |
| 194 | export function acquireLock(lockPath: string): (() => void) | null { |
| 195 | try { |
| 196 | fs.mkdirSync(path.dirname(lockPath), { recursive: true }); |
| 197 | // 'wx' = create exclusive, fail if exists. Atomic check-and-create. |
| 198 | const fd = fs.openSync(lockPath, "wx"); |
| 199 | fs.writeSync(fd, `${process.pid}\n`); |
| 200 | fs.closeSync(fd); |
| 201 | return () => { |
| 202 | try { |
| 203 | fs.unlinkSync(lockPath); |
| 204 | } catch { |
| 205 | // already gone |
| 206 | } |
| 207 | }; |
| 208 | } catch { |
| 209 | // Held — check if holder is alive |
| 210 | try { |
| 211 | const holderPid = parseInt(fs.readFileSync(lockPath, "utf-8").trim(), 10); |
| 212 | if (holderPid && isProcessAlive(holderPid)) return null; |
| 213 | // Stale, reclaim |
| 214 | fs.unlinkSync(lockPath); |
| 215 | return acquireLock(lockPath); |
| 216 | } catch { |
| 217 | return null; |
| 218 | } |
| 219 | } |
| 220 | } |
no test coverage detected