Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/kernel/backends/occt/occtException.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ describe('isOcctWasmPoisoned', () => {
expect(isOcctWasmPoisoned(err)).toBe(true);
});

it('recognizes a broken wasm function table', () => {
const err = new Error('null function or function signature mismatch');
err.name = 'RuntimeError';
expect(isOcctWasmPoisoned(err)).toBe(true);
expect(isOcctWasmPoisoned(new Error('RuntimeError: null function or function signature mismatch'))).toBe(true);
});

it('recognizes worker-wrapped Error messages', () => {
expect(isOcctWasmPoisoned(new Error('RuntimeError: memory access out of bounds'))).toBe(true);
});
Expand Down
22 changes: 5 additions & 17 deletions src/modeling/compute/recomputeEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,24 +594,12 @@ export class RecomputeEngine {
return await this.runPass(records, opts);
} catch (retryErr) {
if (!isOcctWasmPoisoned(retryErr)) throw retryErr;
const message =
// Throw, do not return a per-feature diagnostic. A returned failure
// leaves this dead heap in service and the viewer never gets a mesh.
throw new Error(
`${WASM_POISON_MARKER}: ${describeOcctThrow(retryErr)}. ` +
'OCCT was reset and the full recompute retried; still failing. Restart the host process.';
return {
shapes: new Map(),
diagnostics: [{
target: this.lowerer.target,
code: 'recompute.lowering.exception',
severity: 'error',
message,
hint:
'The OCCT wasm heap was corrupted (often by an embind double-free). ' +
'Reset + retry did not recover; restart the Node/export process or reload Studio.',
}],
health: new Map(),
mechanism: 'unverified',
mechanismFailures: [],
};
'OCCT was reset and the full recompute retried; still failing. Restart the host process.',
);
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/shared/occt/wasmPoison.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ function looksLikeWasmPoisonText(text: string): boolean {
// Emscripten abort() after unrecoverable wasm failure (truncated BREP, etc.).
if (t.includes('aborted()') || t.includes('aborted(')) return true;
if (t.includes('runtimeerror') && t.includes('aborted')) return true;
// Function-table corruption. Prod OCCT workers threw
// "RuntimeError: null function or function signature mismatch" and every
// later feature was recorded as a normal compile failure, so the worker
// stayed up and the viewer never painted.
if (t.includes('function signature mismatch') || t.includes('null function')) return true;
return false;
}

Expand Down
Loading