@botbuddy/cli 1.40.2 → 1.40.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/wait-checkpoint.mjs +22 -8
package/package.json
CHANGED
package/src/wait-checkpoint.mjs
CHANGED
|
@@ -107,6 +107,20 @@ async function processStartedAt(pid) {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// The real process-instance probe behind the ownership fence. Tests inject a
|
|
111
|
+
// deterministic one instead of spawning `ps` (BOT-2031).
|
|
112
|
+
const systemProcessProbe = Object.freeze({
|
|
113
|
+
async isAlive(pid) {
|
|
114
|
+
try { process.kill(pid, 0); }
|
|
115
|
+
catch (error) {
|
|
116
|
+
if (error?.code === "ESRCH") return false;
|
|
117
|
+
return true; // EPERM is deliberately conservative.
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
},
|
|
121
|
+
startedAt: processStartedAt,
|
|
122
|
+
});
|
|
123
|
+
|
|
110
124
|
function installFenceExitHook() {
|
|
111
125
|
if (installedFenceExitHook) return;
|
|
112
126
|
installedFenceExitHook = true;
|
|
@@ -120,7 +134,11 @@ function installFenceExitHook() {
|
|
|
120
134
|
});
|
|
121
135
|
}
|
|
122
136
|
|
|
123
|
-
export function createWaitCheckpointStore({
|
|
137
|
+
export function createWaitCheckpointStore({
|
|
138
|
+
root = process.cwd(),
|
|
139
|
+
now = () => new Date(),
|
|
140
|
+
processProbe = systemProcessProbe,
|
|
141
|
+
} = {}) {
|
|
124
142
|
const worktree = resolve(root);
|
|
125
143
|
const directory = join(worktree, ".botbuddy", "waits");
|
|
126
144
|
const pathFor = (id) => {
|
|
@@ -184,12 +202,8 @@ export function createWaitCheckpointStore({ root = process.cwd(), now = () => ne
|
|
|
184
202
|
return lock;
|
|
185
203
|
};
|
|
186
204
|
const lockIsLive = async (lock) => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (error?.code === "ESRCH") return false;
|
|
190
|
-
return true; // EPERM is deliberately conservative.
|
|
191
|
-
}
|
|
192
|
-
const startedAt = await processStartedAt(lock.pid);
|
|
205
|
+
if (!await processProbe.isAlive(lock.pid)) return false;
|
|
206
|
+
const startedAt = await processProbe.startedAt(lock.pid);
|
|
193
207
|
// A live PID without a matching process-instance identity is never ownership proof.
|
|
194
208
|
return startedAt != null && startedAt === lock.process_started_at;
|
|
195
209
|
};
|
|
@@ -310,7 +324,7 @@ export function createWaitCheckpointStore({ root = process.cwd(), now = () => ne
|
|
|
310
324
|
const localWaitId = safeId(id);
|
|
311
325
|
await ensureDirectory();
|
|
312
326
|
const path = lockPathFor(localWaitId);
|
|
313
|
-
const processStartedAtValue = await
|
|
327
|
+
const processStartedAtValue = await processProbe.startedAt(process.pid);
|
|
314
328
|
if (!processStartedAtValue) {
|
|
315
329
|
throw new WaitCheckpointError("wait_owner_unknown", "could not establish this process identity for wait recovery");
|
|
316
330
|
}
|