Fix frozen provider graph and retain snapshots across failed launches
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
d2ecec3359
commit
855aa1b007
|
|
@ -296,7 +296,7 @@ COPY packages ./packages
|
|||
COPY server/package.json ./server/package.json
|
||||
COPY ui/package.json ./ui/package.json
|
||||
COPY cli/package.json ./cli/package.json
|
||||
ARG PAPERCLIP_RUNNER_LOCK_SHA256=21aa3df50da53c338660b9f5f2611e9d46c896ad05c0e7a9976185ebce340f52
|
||||
ARG PAPERCLIP_RUNNER_LOCK_SHA256=101481086be52f63be8b83b9047d70aeb0995a4ebe1deb638a43346386f9085e
|
||||
RUN printf '%s pnpm-lock.yaml\n' "${PAPERCLIP_RUNNER_LOCK_SHA256}" > /tmp/provider-lock.sha256 \
|
||||
&& sha256sum -c /tmp/provider-lock.sha256 \
|
||||
&& pnpm install --frozen-lockfile --filter '@paperclipai/paperclip-runner...'
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ COPY cli/package.json ./cli/package.json
|
|||
# The complete resolved lock (including transitive integrity hashes) is reviewed.
|
||||
# Reject registry-time drift BEFORE installing packages or running lifecycle code.
|
||||
# Refresh this digest together with source/provider dependency changes.
|
||||
ARG PAPERCLIP_RUNNER_LOCK_SHA256=21aa3df50da53c338660b9f5f2611e9d46c896ad05c0e7a9976185ebce340f52
|
||||
ARG PAPERCLIP_RUNNER_LOCK_SHA256=101481086be52f63be8b83b9047d70aeb0995a4ebe1deb638a43346386f9085e
|
||||
RUN printf '%s pnpm-lock.yaml\n' "${PAPERCLIP_RUNNER_LOCK_SHA256}" > /tmp/provider-lock.sha256 \
|
||||
&& sha256sum -c /tmp/provider-lock.sha256 \
|
||||
&& pnpm install --frozen-lockfile --filter '@paperclipai/paperclip-runner...'
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -778,6 +778,22 @@ describe("ACPX installation integrity", () => {
|
|||
expect(() => lease.spawn()).toThrow("Verified ACPX command lease is closed");
|
||||
});
|
||||
|
||||
it("a failed reusable launch preserves the snapshot of an already spawned child", async () => {
|
||||
const fixture = await installationFixture();
|
||||
const installation = await verifyQualifiedAcpxInstallation(fixture.profile, fixture.resolve);
|
||||
const lease = await installation.openCommand({ reusable: true });
|
||||
try {
|
||||
const output = expectPinnedOutput(lease.spawn(), "verified");
|
||||
// Node rejects this argument synchronously, before creating another child.
|
||||
expect(() => lease.spawn(["invalid\0argument"])).toThrow();
|
||||
await lease.close();
|
||||
await output;
|
||||
expect(() => lease.spawn()).toThrow("Verified ACPX command lease is closed");
|
||||
} finally {
|
||||
await lease.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("launches the verified bytes after the open inode is modified", async () => {
|
||||
const fixture = await installationFixture();
|
||||
const installation = await verifyQualifiedAcpxInstallation(
|
||||
|
|
|
|||
|
|
@ -1503,6 +1503,16 @@ function commandLease(
|
|||
],
|
||||
},
|
||||
);
|
||||
activeChildren++;
|
||||
let childSettled = false;
|
||||
const settleChild = (): void => {
|
||||
if (childSettled) return;
|
||||
childSettled = true;
|
||||
activeChildren--;
|
||||
void closeSnapshotIfIdle().catch(() => undefined);
|
||||
};
|
||||
child.once("exit", settleChild);
|
||||
child.once("error", settleChild);
|
||||
if (guarded) {
|
||||
const guardianOwnerPipe = child.stdio[
|
||||
providerOwnershipFd - 1
|
||||
|
|
@ -1534,22 +1544,14 @@ function commandLease(
|
|||
launchBytes.fill(0);
|
||||
verifiedBytes.fill(0);
|
||||
releaseDirectoriesBestEffort();
|
||||
void privateSnapshot?.close();
|
||||
closed = true;
|
||||
void closeSnapshotIfIdle().catch(() => undefined);
|
||||
throw error;
|
||||
}
|
||||
activeChildren++;
|
||||
let childSettled = false;
|
||||
const settleChild = (): void => {
|
||||
if (childSettled) return;
|
||||
childSettled = true;
|
||||
activeChildren--;
|
||||
void closeSnapshotIfIdle().catch(() => undefined);
|
||||
};
|
||||
child.once("exit", settleChild);
|
||||
child.once("error", settleChild);
|
||||
if (!reusable) releaseDirectoriesBestEffort();
|
||||
const sourceInput = child.stdio[COMMAND_SOURCE_FD] as Writable | null;
|
||||
if (sourceInput === null) {
|
||||
closed = true;
|
||||
consumed = true;
|
||||
launchBytes.fill(0);
|
||||
verifiedBytes.fill(0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue