Skip to content

fix(task-details): prevent memory leaks and race conditions in task subscription #479

@siddiqui7864

Description

@siddiqui7864

Description

Three critical issues in TaskDetails.tsx:
(1) getPluginSchema promise updates state after unmount
(2) loadTask() called without race protection
(3) state setters without mounted check in useTaskSubscription

Current Code - Issue 1 (Line ~420)

getPluginSchema(statusData.plugin_id).then(setSchema).catch(() => setSchema(null))

Current Code - Issue 2 (Line ~376)

onStatus: (status) => {
setTask((prev: Task | null) => prev ? { ...prev, status } : null)
if (['completed', 'failed', 'cancelled'].includes(status)) {
loadTask()
}
}

Current Code - Issue 3 (Lines 365-380)

onStatus: (status) => {
setTask((prev: Task | null) => prev ? { ...prev, status } : null)
if (['completed', 'failed', 'cancelled'].includes(status)) {
loadTask()
}
},
onPhase: (phase) => {
setScanPhase(phase)
},
onOutput: (chunk) => {
setRawOutput((prev) => prev + chunk)
}

Proposed Fix

// Add mounted ref at component top
const isMounted = useRef(true)

useEffect(() => {
return () => { isMounted.current = false }
}, [])

// Update getPluginSchema with mount check
getPluginSchema(statusData.plugin_id)
.then(schema => isMounted.current && setSchema(schema))
.catch(() => isMounted.current && setSchema(null))

// Add request sequence for loadTask race protection
const loadTaskSeqRef = useRef(0)

async function loadTask() {
const currentSeq = ++loadTaskSeqRef.current
if (!isMounted.current) return
// ... rest of function with sequence checks
}

// Add mount checks to all state setters in useTaskSubscription
onStatus: (status) => {
if (!isMounted.current) return
setTask((prev: Task | null) => prev ? { ...prev, status } : null)
if (['completed', 'failed', 'cancelled'].includes(status)) {
loadTask()
}
},
onPhase: (phase) => {
if (!isMounted.current) return
setScanPhase(phase)
},
onOutput: (chunk) => {
if (!isMounted.current) return
setRawOutput((prev) => prev + chunk)
}

Files Changed

  • src/pages/TaskDetails.tsx

/label ~bug ~critical ~performance

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions