mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-17 10:06:42 +02:00
fix: record Linux process birth from kernel ticks
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
d26ff52272
commit
9fdcefcc34
10 files changed
+149
-22
No files matched your search
@@ -89,18 +89,20 @@ describe("hot-restart path compatibility", () => {
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
it("reads Linux process start time from proc metadata", async () => {
|
||||
it("reads Linux process birth from kernel ticks rather than proc directory metadata", async () => {
|
||||
await expect(
|
||||
readProcessStartedAt(123, {
|
||||
platform: "linux",
|
||||
stat: async (target) => {
|
||||
expect(target).toBe("/proc/123");
|
||||
return {
|
||||
ctimeMs: Date.parse("2026-08-01T01:00:00.123Z"),
|
||||
};
|
||||
linuxProcessStart: {
|
||||
clockTicksPerSecond: 100,
|
||||
readFile: (target) => target === "/proc/stat"
|
||||
? `btime ${Date.parse("2026-08-01T01:00:00.000Z") / 1000}\n`
|
||||
: target === "/proc/123/stat"
|
||||
? `123 (runner) S ${Array(18).fill("0").join(" ")} 123\n`
|
||||
: (() => { throw new Error("Unexpected proc read"); })(),
|
||||
},
|
||||
}),
|
||||
).resolves.toBe("2026-08-01T01:00:00.123Z");
|
||||
).resolves.toBe("2026-08-01T01:00:01.230Z");
|
||||
});
|
||||
|
||||
it("reads macOS process start time through ps", async () => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { execFile } from "node:child_process";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { readLinuxProcessStartedAt, type LinuxProcessStartOptions } from "@paperclipai/paperclip-runner";
|
||||
import {
|
||||
resolvePaperclipHomeDir,
|
||||
resolvePaperclipInstanceId,
|
||||
@@ -14,7 +15,6 @@ const HOT_RESTART_LOCK_STALE_MS = 30_000;
|
||||
const HOT_RESTART_LOCK_TIMEOUT_MS = 10_000;
|
||||
|
||||
type ProcessCommandRunner = (command: string, args: string[]) => Promise<string>;
|
||||
type ProcessStatReader = (target: string) => Promise<{ ctimeMs: number }>;
|
||||
|
||||
export type HotRestartIntentRun = {
|
||||
runId: string;
|
||||
@@ -178,17 +178,15 @@ export async function readProcessStartedAt(
|
||||
pid: number,
|
||||
options: {
|
||||
platform?: NodeJS.Platform;
|
||||
stat?: ProcessStatReader;
|
||||
linuxProcessStart?: LinuxProcessStartOptions;
|
||||
runCommand?: ProcessCommandRunner;
|
||||
} = {},
|
||||
) {
|
||||
const platform = options.platform ?? process.platform;
|
||||
const stat = options.stat ?? fs.stat;
|
||||
const runCommand = options.runCommand ?? runProcessCommand;
|
||||
|
||||
if (platform === "linux") {
|
||||
const processStat = await stat(`/proc/${pid}`);
|
||||
return new Date(processStat.ctimeMs).toISOString();
|
||||
return readLinuxProcessStartedAt(pid, options.linuxProcessStart);
|
||||
}
|
||||
|
||||
if (["darwin", "freebsd", "openbsd", "aix", "sunos"].includes(platform)) {
|
||||
|
||||
Reference in new issue
Block a user