GPU context cleanup, exit guards, and error handling fixes#1661
GPU context cleanup, exit guards, and error handling fixes#1661richiemcilroy merged 19 commits intomainfrom
Conversation
Paragon SummaryThis pull request review identified 1 issue across 1 category in 8 files. The review analyzed code changes, potential bugs, security vulnerabilities, performance issues, and code quality concerns using automated analysis tools. This PR centralizes GPU context initialization into Key changes:
Confidence score: 4/5
8 files reviewed, 1 comment Severity breakdown: Medium: 1 |
apps/web/app/(org)/dashboard/_components/Notifications/NotificationItem.tsx
Show resolved
Hide resolved
|
@greptileai please re-review this pr. |
| return `/s/${notification.videoId}`; | ||
| } | ||
|
|
||
| return `/s/${(notification as APINotification).videoId}`; |
There was a problem hiding this comment.
The (notification as APINotification) cast is a bit of a smell here (usually comes from notification being never after an exhaustive switch). Might be clearer to keep the fallback via a default arm and drop the post-switch return.
| return `/s/${(notification as APINotification).videoId}`; | |
| function getLink(notification: APINotification) { | |
| switch (notification.type) { | |
| case "reply": | |
| return `/s/${notification.videoId}/?reply=${notification.comment.id}`; | |
| case "comment": | |
| case "reaction": | |
| return `/s/${notification.videoId}/?comment=${notification.comment.id}`; | |
| case "view": | |
| case "anon_view": | |
| return `/s/${notification.videoId}`; | |
| default: | |
| return `/s/${notification.videoId}`; | |
| } | |
| } |
cap_rendering, eliminating duplicated GPU init logic across desktop and rendering cratesapp_is_exitingguards to background task loops and window event handlers to prevent spurious errors during shutdownunwrap()calls with proper error propagation in editor IPC commands and dock icon visibility checksrequest_app_exitfor tray quit instead of immediateapp.exit(0)Greptile Summary
This PR delivers three tightly-scoped improvements: (1) centralizing wgpu instance creation and software-adapter detection into
cap_renderingso all crates share the same Windows DX12-probe logic, (2) addingapp_is_exitingguards to background task loops and window event handlers to prevent spurious errors during shutdown, and (3) a collection of error-handling hardening changes (replacingunwrap()with proper propagation, usingrequest_app_exitfrom the tray, adding Windows display-affinity diagnostics, and skipping the performance suite on CI when only a software adapter is present).Key changes:
crates/rendering/src/lib.rs: Newcreate_wgpu_instance,is_software_wgpu_adapter, andprobe_software_adapterpublic functions extract all GPU-selection logic from desktop/rendering consumers.apps/desktop/src-tauri/src/gpu_context.rs: Drops 26 lines of Windows/non-Windows#[cfg]branching; now a one-liner call tocap_rendering::create_wgpu_instance().apps/desktop/src-tauri/src/lib.rs:app_is_exitinghelper queriesAppExitStatesafely viatry_state(no panic before state registration). Guards added at loop tops in four background tasks;CloseRequested/Moved/Focused/Destroyedwindow events short-circuit during exit. Twounwrap()calls in IPC handlers replaced withmap_err(|e| e.to_string())?. The dock-icon predicate now usesunwrap_or(false)instead of panicking on unknown window labels.apps/desktop/src-tauri/src/tray.rs: Tray quit now spawnsrequest_app_exitasynchronously; thecompare_exchangeinAppExitState::begin()makes repeated clicks safe.apps/desktop/src-tauri/src/windows.rs: Windows-onlylog_window_content_protectiondiagnostic logs the actual vs. expectedWDA_*affinity value and warns on OS builds below 19041 whereWDA_EXCLUDEFROMCAPTUREis unsupported.crates/cap-test/src/suites/performance.rs:probe_windows_ci_software_adapterearly-returns pre-built "skipped" results whenGITHUB_ACTIONS=trueand only a software renderer is available, avoiding false CI failures.apps/web/…: TypeScript type-safety fixes across 20+ test files (!non-null assertions, optional chaining onIntersectionObserverentries,!guards on array-index accesses),S3Buckets.getBucketAccess(Option.none())call-site updates, and branded-type ID construction in DB queries.Confidence Score: 4/5
?overunwrap). The tray-quit path and Windows diagnostic code add new surface area but are correctly guarded and do not affect the happy path on macOS. The TypeScript changes are pure type-safety improvements. The one point deducted is for the minor inconsistency in exit-guard placement (top-only vs. top-and-bottom) across the watcher loops, and for the Windows content-protection diagnostic path which exercisesunsafeWin32 APIs in a new way that cannot be fully tested in CI.apps/desktop/src-tauri/src/lib.rs.Important Files Changed
create_wgpu_instance,is_software_wgpu_adapter,probe_software_adapter) that centralize GPU initialization logic previously duplicated across crates. Also addsfrom_shared_deviceconstructor andadapter_name()accessor toRenderVideoConstants, and introduces the privateadapter_namefield to avoid repeatedget_info()calls. Changes are well-structured with no issues found.cap_rendering::create_wgpu_instance(). Also improves software adapter detection by using the sharedis_software_wgpu_adapterhelper and logs thedevice_typefield for richer diagnostics. Clean improvement with no issues.app_is_exitinghelper that safely queriesAppExitStateviatry_state(returningfalsewhen not yet registered). Guards are added at the top of four background task loops and insideWindowEvent::Destroyed. TheCloseRequested/Moved/Focusedevents are short-circuited at the event-handler entry. Twounwrap()calls in editor IPC commands are replaced with propermap_err+?propagation. Note:spawn_devices_snapshot_emitterhas guards at both the top and bottom of its loop (good), whilespawn_microphone_watcherandspawn_camera_watcheronly guard at the top — this is not a bug but is slightly inconsistent.cap_rendering::create_wgpu_instance()instead of the old barewgpu::InstanceDescriptor::default(), completing the centralization goal. GPU resources are wrapped intocap_rendering::SharedWgpuDeviceand passed to the newRenderVideoConstants::from_shared_deviceconstructor. Theis_software_adapterflag is now correctly computed viais_software_wgpu_adapter. Clean refactor, no issues.app.exit(0)on tray-quit with a spawned async task callingrequest_app_exit. This ensures the graceful shutdown path (cleanup, exit watchdog, etc.) is invoked, and double-clicks are safe becauseAppExitState::begin()usescompare_exchange.log_window_content_protectiondiagnostic function that callsGetWindowDisplayAffinityand logs a warning on mismatch. Hoistsshould_protectcomputation before window builder to allow reuse. Also adds a Windows-build version check (build < 19041) warning forWDA_EXCLUDEFROMCAPTUREunsupported on older builds. Thedisplay_affinity_namehelper uses hardcoded integer literals for the match arms, which is acceptable since the Windows API constants cannot be used asconstpattern values in Rust. The dock-icon fix (unwrap_or(false)vs panic) is correct and safe.probe_windows_ci_software_adapter(no-op on non-Windows, only active whenGITHUB_ACTIONS=trueon Windows) that callscap_rendering::probe_software_adapter()and returns pre-built "skipped" results if a software adapter is detected, avoiding meaningless performance gate failures on CI runners without hardware GPUs. Well structured; the non-Windows stub uses_recording_pathcorrectly to suppress unused-variable warnings.S3Buckets.getBucketAccess()to passOption.none(), matching a changed function signature in the backend layer. AddsOptionimport fromeffect. Routine API-compatibility update.Sequence Diagram
sequenceDiagram participant App as Desktop App participant GpuCtx as gpu_context.rs participant Rendering as cap_rendering participant WGPU as wgpu Note over App,WGPU: Shared GPU Context Initialization (centralized) App->>GpuCtx: init_gpu_inner() GpuCtx->>Rendering: create_wgpu_instance() alt Windows Rendering->>WGPU: Instance::new(DX12) WGPU-->>Rendering: dx12_instance Rendering->>WGPU: request_adapter(DX12, high-perf) alt DX12 available WGPU-->>Rendering: Ok(adapter) Rendering-->>GpuCtx: dx12_instance else DX12 not available WGPU-->>Rendering: Err Rendering->>WGPU: Instance::new(default) WGPU-->>Rendering: default_instance Rendering-->>GpuCtx: default_instance end else Non-Windows Rendering->>WGPU: Instance::new(default) WGPU-->>Rendering: instance Rendering-->>GpuCtx: instance end GpuCtx->>WGPU: request_adapter(high-perf, no-fallback) alt Hardware adapter found WGPU-->>GpuCtx: Ok(hardware_adapter) GpuCtx->>Rendering: is_software_wgpu_adapter(info) Rendering-->>GpuCtx: bool (DeviceType::Cpu or MBRD name) GpuCtx-->>GpuCtx: (adapter, is_software) else No hardware adapter WGPU-->>GpuCtx: Err GpuCtx->>WGPU: request_adapter(low-power, force-fallback) WGPU-->>GpuCtx: Ok(software_adapter) GpuCtx-->>GpuCtx: (software_adapter, true) end GpuCtx->>WGPU: request_device(adapter) WGPU-->>GpuCtx: (device, queue) GpuCtx-->>App: SharedGpuContext Note over App,WGPU: Graceful Shutdown via Tray Quit App->>App: TrayItem::Quit clicked App->>App: tokio::spawn(request_app_exit) App->>App: AppExitState::begin() → compare_exchange App->>App: spawn_exit_watchdog (force-exit after 8s) App->>App: cleanup_app_resources_for_exit loop Background tasks App->>App: app_is_exiting() → true → break end App->>App: app.exit(0)Prompt To Fix All With AI
Last reviewed commit: acc8ada