MCPcopy
hub / github.com/codeaashu/claude-code / acquireLock

Function acquireLock

src/utils/autoUpdater.ts:176–249  ·  view source on GitHub ↗

* Attempts to acquire a lock for auto-updater * @returns true if lock was acquired, false if another process holds the lock

()

Source from the content-addressed store, hash-verified

174 * @returns true if lock was acquired, false if another process holds the lock
175 */
176async function acquireLock(): Promise<boolean> {
177 const fs = getFsImplementation()
178 const lockPath = getLockFilePath()
179
180 // Check for existing lock: 1 stat() on the happy path (fresh lock or ENOENT),
181 // 2 on stale-lock recovery (re-verify staleness immediately before unlink).
182 try {
183 const stats = await fs.stat(lockPath)
184 const age = Date.now() - stats.mtimeMs
185 if (age < LOCK_TIMEOUT_MS) {
186 return false
187 }
188 // Lock is stale, remove it before taking over. Re-verify staleness
189 // immediately before unlinking to close a TOCTOU race: if two processes
190 // both observe the stale lock, A unlinks + writes a fresh lock, then B
191 // would unlink A's fresh lock and both believe they hold it. A fresh
192 // lock has a recent mtime, so re-checking staleness makes B back off.
193 try {
194 const recheck = await fs.stat(lockPath)
195 if (Date.now() - recheck.mtimeMs < LOCK_TIMEOUT_MS) {
196 return false
197 }
198 await fs.unlink(lockPath)
199 } catch (err) {
200 if (!isENOENT(err)) {
201 logError(err as Error)
202 return false
203 }
204 }
205 } catch (err) {
206 if (!isENOENT(err)) {
207 logError(err as Error)
208 return false
209 }
210 // ENOENT: no lock file, proceed to create one
211 }
212
213 // Create lock file atomically with O_EXCL (flag: 'wx'). If another process
214 // wins the race and creates it first, we get EEXIST and back off.
215 // Lazy-mkdir the config dir on ENOENT.
216 try {
217 await writeFile(lockPath, `${process.pid}`, {
218 encoding: 'utf8',
219 flag: 'wx',
220 })
221 return true
222 } catch (err) {
223 const code = getErrnoCode(err)
224 if (code === 'EEXIST') {
225 return false
226 }
227 if (code === 'ENOENT') {
228 try {
229 // fs.mkdir from getFsImplementation() is always recursive:true and
230 // swallows EEXIST internally, so a dir-creation race cannot reach the
231 // catch below — only writeFile's EEXIST (true lock contention) can.
232 await fs.mkdir(getClaudeConfigHomeDir())
233 await writeFile(lockPath, `${process.pid}`, {

Callers 1

installGlobalPackageFunction · 0.85

Calls 5

getFsImplementationFunction · 0.85
getLockFilePathFunction · 0.85
isENOENTFunction · 0.85
getErrnoCodeFunction · 0.85
logErrorFunction · 0.70

Tested by

no test coverage detected