mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-22 20:52:23 +02:00
[eric] crash: orphan-prune serializes app-card teardown too (deleting several apps from the Views page ripped their webviews out in one pass = same GPU SIGSEGV)
This commit is contained in:
@@ -14,7 +14,6 @@ import {
|
||||
addBrowserCard,
|
||||
addViewCard,
|
||||
resetLayout,
|
||||
removeViewCard,
|
||||
clearPendingFocusBrowserId,
|
||||
clearPendingFocusViewCardId,
|
||||
clearPendingFocusWorkflowId,
|
||||
@@ -30,6 +29,7 @@ import { dashboardWs } from '@/shared/ws/WebSocketManager';
|
||||
import { initBrowserCommandHandler } from '@/shared/browserCommandHandler';
|
||||
import { getKeepAliveBrowserIds } from '@/shared/browserFocus';
|
||||
import { prepareDashboardSwitch } from '@/shared/dashboardSwitchTeardown';
|
||||
import { removeViewCardCleanly } from '@/shared/viewTeardown';
|
||||
import { clearPendingBrowserUrl, clearPendingFocusAgentId } from '@/shared/state/tempStateSlice';
|
||||
import { API_BASE } from '@/shared/config';
|
||||
import type { CanvasActions } from '../interaction/useCanvasControls';
|
||||
@@ -319,9 +319,11 @@ export function useDashboardLifecycle({
|
||||
// Prune orphan view cards whose underlying output was deleted (e.g. via the Views page). Without this, the layout entry persists in the minimap and contentBounds even though DashboardViewCard renders nothing. Gated on outputsRefetched (THIS open's fresh fetch), NOT the sticky global outputsLoaded: on a freshly-imported dashboard the global flag is already true from a prior dashboard, so the old gate pruned the just-imported app card against a stale apps list and the debounced save persisted the wipe.
|
||||
useEffect(() => {
|
||||
if (!layoutInitialized || !outputsRefetched) return;
|
||||
for (const outputId of Object.keys(viewCards)) {
|
||||
if (!outputs[outputId]) dispatch(removeViewCard(outputId));
|
||||
}
|
||||
const orphans = Object.keys(viewCards).filter((id) => !outputs[id]);
|
||||
if (orphans.length === 0) return;
|
||||
// Serialize teardown (quiesce each GPU surface first): pruning several orphaned app cards in one
|
||||
// pass would rip their webviews out simultaneously, the same GPU-process SIGSEGV as mass delete.
|
||||
void (async () => { for (const id of orphans) await removeViewCardCleanly(id, dispatch); })();
|
||||
}, [layoutInitialized, outputsRefetched, viewCards, outputs, dispatch]);
|
||||
|
||||
// On first load after outputs settle, snapshot every existing Output id as "already accounted for." Any output that ARRIVES later (typically the agent:output_upserted WS broadcast the backend fires the instant a view-builder session is seeded, at session start) whose session_id points at a view-builder chat on this dashboard gets a view card dropped on the canvas right away. Per-mount tracked so a manual close after auto-open stays closed. Prior approach keyed off a pending-set populated inside launchAndSendFirstMessage.then(): the WS upsert won the race and the effect saw an empty set, so the card didn't pop until the session-end meta-sync re-broadcast.
|
||||
|
||||
Reference in New Issue
Block a user