tryAcquireLock method
Acquire: write PID -> mtime = now. Returns the pre-acquire mtime (for rollback), or null if blocked / lost a race.
Implementation
Future<int?> tryAcquireLock() async {
int? mtimeMs;
int? holderPid;
try {
final results = await Future.wait([
statMtimeMs(_lockPath),
readFileOrNull(_lockPath),
]);
mtimeMs = results[0] as int?;
final raw = results[1] as String?;
if (raw != null) {
final parsed = int.tryParse(raw.trim());
holderPid = parsed;
}
} catch (_) {
// ENOENT — no prior lock.
}
if (mtimeMs != null &&
DateTime.now().millisecondsSinceEpoch - mtimeMs < _holderStaleMs) {
if (holderPid != null && isProcessRunning(holderPid)) {
logDebug(
'[autoDream] lock held by live PID $holderPid '
'(mtime ${((DateTime.now().millisecondsSinceEpoch - mtimeMs) / 1000).round()}s ago)',
);
return null;
}
// Dead PID or unparseable body — reclaim.
}
// Memory dir may not exist yet.
await mkdirRecursive(getAutoMemPath());
await writeFile(_lockPath, pid.toString());
// Two reclaimers both write -> last wins the PID. Loser bails on re-read.
String? verify;
try {
verify = await readFileOrNull(_lockPath);
} catch (_) {
return null;
}
if (verify == null || int.tryParse(verify.trim()) != pid) return null;
return mtimeMs ?? 0;
}