{"record":{"id":"e51663225e370a8f","repo":"GraphiteEditor/Graphite","slug":"error-setting-ctrl-c-handler","errorCode":null,"errorMessage":"Error setting Ctrl-C handler","messagePattern":"Error setting Ctrl-C handler","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"desktop/src/app.rs","lineNumber":72,"sourceCode":"impl App {\n\tpub(crate) fn init() {\n\t\tWindow::init();\n\t}\n\n\tpub(crate) fn new(\n\t\tui: UiInstance,\n\t\twgpu_context: WgpuContext,\n\t\tapp_event_receiver: Receiver<AppEvent>,\n\t\tapp_event_scheduler: AppEventScheduler,\n\t\tpreferences: Preferences,\n\t\tlaunch_documents: Vec<PathBuf>,\n\t) -> Self {\n\t\tlet ctrlc_app_event_scheduler = app_event_scheduler.clone();\n\t\tctrlc::set_handler(move || {\n\t\t\ttracing::info!(\"Termination signal received, exiting...\");\n\t\t\tctrlc_app_event_scheduler.schedule(AppEvent::Exit);\n\t\t})\n\t\t.expect(\"Error setting Ctrl-C handler\");\n\n\t\tlet exiting = Arc::new(AtomicBool::new(false));\n\n\t\tlet rendering_app_event_scheduler = app_event_scheduler.clone();\n\t\tlet (start_render_sender, start_render_receiver) = std::sync::mpsc::sync_channel(1);\n\t\tlet exiting_clone = exiting.clone();\n\t\tstd::thread::spawn(move || {\n\t\t\tlet runtime = tokio::runtime::Runtime::new().unwrap();\n\t\t\tloop {\n\t\t\t\tlet result = runtime.block_on(DesktopWrapper::execute_node_graph());\n\t\t\t\trendering_app_event_scheduler.schedule(AppEvent::NodeGraphExecutionResult(result));\n\t\t\t\tlet _ = start_render_receiver.recv_timeout(Duration::from_millis(10));\n\t\t\t\tif exiting_clone.load(Ordering::Relaxed) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/desktop/src/app.rs#L54-L90","documentation":"Panic when ctrlc::set_handler fails while the desktop app installs its Ctrl-C/SIGINT handler that schedules AppEvent::Exit. The ctrlc crate reports an error primarily when a handler is already installed for this process (Error::MultipleHandlers), and on some platforms when the underlying OS signal registration call returns an error. Only one ctrl-c handler may exist per process.","triggerScenarios":"App::new being constructed twice in one process (integration tests, embedders) so set_handler is called again; another crate or dependency in the same binary also registering a ctrlc handler; rare OS-level sigaction/SetConsoleCtrlHandler failures.","commonSituations":"Test harnesses that instantiate the full desktop App multiple times in a single test process; a dependency (CLI framework, tracing setup, CEF wrapper) that already owns the ctrl-c handler; embedding the desktop app inside another host process.","solutions":["Ensure the app object that installs the Ctrl-C handler is created exactly once per process","Search the dependency tree for other ctrlc crate users and consolidate to a single owner of the handler","In tests, construct the app once or factor the handler installation out of the constructor","If a second registration is genuinely needed, switch to a channel-based handler shared by both call sites"],"exampleFix":"// before\nctrlc::set_handler(move || {\n\ttracing::info!(\"Termination signal received, exiting...\");\n\tctrlc_app_event_scheduler.schedule(AppEvent::Exit);\n})\n.expect(\"Error setting Ctrl-C handler\");\n\n// after\nif let Err(e) = ctrlc::set_handler(move || {\n\ttracing::info!(\"Termination signal received, exiting...\");\n\tctrlc_app_event_scheduler.schedule(AppEvent::Exit);\n}) {\n\ttracing::warn!(\"Ctrl-C handler not installed (already set or unsupported): {e}\");\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match ctrlc::set_handler(move || {\n\ttracing::info!(\"Termination signal received, exiting...\");\n\tctrlc_app_event_scheduler.schedule(AppEvent::Exit);\n}) {\n\tOk(()) => {}\n\tErr(e) if e.kind() == ctrlc::ErrorKind::MultipleHandlers => {\n\t\ttracing::warn!(\"Ctrl-C handler already set elsewhere; skipping\");\n\t}\n\tErr(e) => tracing::warn!(\"Ctrl-C handler not installed: {e}\"),\n}","preventionTips":["Construct the app (and thus install the handler) exactly once per process, especially in tests","Search the dependency tree for other ctrlc users before adding another handler","Treat signal-handler installation as best-effort for a GUI app: log and continue rather than panic"],"tags":["rust","ctrlc","signals","process-lifecycle","app-initialization"],"backgroundTag":"signal-handler-already-set","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}