{"record":{"id":"289cb074d1be7cf5","repo":"GraphiteEditor/Graphite","slug":"failed-to-create-control-channel","errorCode":null,"errorMessage":"Failed to create control channel","messagePattern":"Failed to create control channel","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"desktop/ui/src/remote/host.rs","lineNumber":31,"sourceCode":"use crate::platform::mac;\n\npub(crate) fn run() {\n\t// Ignore SIGINT, the controlling process is responsible for shutting down the host\n\t#[cfg(any(target_os = \"linux\", target_os = \"macos\"))]\n\tunsafe {\n\t\tlibc::signal(libc::SIGINT, libc::SIG_IGN);\n\t}\n\n\tlet args: Vec<String> = std::env::args().collect();\n\tlet config = HostConfig::from_args(&args).expect(\"CEF host started without a valid host config argument\");\n\tlet acceleration_requested = config.acceleration;\n\n\t#[cfg(target_os = \"macos\")]\n\tmac::spawn_parent_watchdog(config.main_pid);\n\n\tlet bootstrap = IpcSender::<EventMessage>::connect(config.server.clone()).expect(\"Failed to connect to the main process bootstrap server\");\n\tlet event_sender = Arc::new(Mutex::new(bootstrap));\n\tlet (control_sender, control_receiver) = ipc_channel::ipc::channel::<HostControlMessage>().expect(\"Failed to create control channel\");\n\n\t#[cfg(feature = \"accelerated_paint\")]\n\tlet plane = if acceleration_requested { PlaneSender::from_config(&config, event_sender.clone()) } else { None };\n\t#[cfg(feature = \"accelerated_paint\")]\n\tlet acceleration = plane.is_some();\n\t#[cfg(not(feature = \"accelerated_paint\"))]\n\tlet acceleration = {\n\t\tif acceleration_requested {\n\t\t\ttracing::error!(\"UI acceleration requested but the accelerated_paint feature is disabled; using software frames\");\n\t\t}\n\t\tfalse\n\t};\n\n\tevent_sender\n\t\t.lock()\n\t\t.expect(\"The host message sender cannot be poisoned before threads exist\")\n\t\t.send(EventMessage::Hello {\n\t\t\tpid: std::process::id(),","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/desktop/ui/src/remote/host.rs#L13-L49","documentation":"Panic when ipc_channel::ipc::channel::<HostControlMessage>() fails. This call creates the OS-backed channel (socketpair on Unix, named pipe on Windows) that the host sends to the main process inside its Hello message for reverse-direction control messages. Channel creation fails when the process is out of file descriptors (EMFILE), when kernel object limits are hit, or when the sandbox blocks the underlying syscall.","triggerScenarios":"The UI host process exhausting its fd limit because many CEF browsers/pipes/sockets are open; a low ulimit -n in the service/container the host runs under; a seccomp/LD_PRELOAD sandbox interfering with socketpair creation.","commonSituations":"Long editor sessions accumulating leaked file descriptors; containers or systemd services started with LimitNOFILE low; heavy multi-window usage spawning many IPC channels; CI environments with restrictive rlimits.","solutions":["Raise the file-descriptor limit for the app (ulimit -n before launch, LimitNOFILE= in systemd, --ulimit nofile= in docker)","Inspect /proc/<host-pid>/fd to count open descriptors and find leaks if the failure appears over time","Restart the app to release leaked descriptors and confirm the limit was the cause","If sandboxed, allow the socketpair syscall family in the security policy"],"exampleFix":"# before (shell)\n./graphite  # host panics: Failed to create control channel\n\n# after\nulimit -n 4096\n./graphite","handlingStrategy":"retry","validationCode":"// Cheap canary: if fd count is near the limit, channel creation is likely to fail\nfn fd_headroom(threshold: usize) -> bool {\n\tlet open = std::fs::read_dir(\"/proc/self/fd\").map(|d| d.count()).unwrap_or(0);\n\topen < threshold\n}","typeGuard":null,"tryCatchPattern":"let (control_sender, control_receiver) = match ipc_channel::ipc::channel::<HostControlMessage>() {\n\tOk(ch) => ch,\n\tErr(e) if e.to_string().contains(\"Too many open files\") => {\n\t\tstd::thread::sleep(Duration::from_millis(50));\n\t\tipc_channel::ipc::channel::<HostControlMessage>().expect(\"control channel creation failed after retry\")\n\t}\n\tErr(e) => panic!(\"Failed to create control channel: {e}\"),\n};","preventionTips":["Launch the app with a generous file-descriptor limit (LimitNOFILE / ulimit -n 4096+)","Track open descriptor counts in long sessions to catch leaks before they become panics","Retry once on EMFILE-style errors; fd exhaustion can be transient under load"],"tags":["rust","ipc-channel","file-descriptors","os-limits","multi-process"],"backgroundTag":"socketpair-emfile","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}