{"record":{"id":"226964a51424f888","repo":"rust-lang/rust-analyzer","slug":"tried-to-set-qos-of-thread-which-has-opted-out-of","errorCode":null,"errorMessage":"tried to set QoS of thread which has opted out of QoS (os error {errno})","messagePattern":"tried to set QoS of thread which has opted out of QoS \\(os error (.+?)\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/stdx/src/thread/intent.rs","lineNumber":198,"sourceCode":"        };\n\n        let code = unsafe { libc::pthread_set_qos_class_self_np(c, 0) };\n\n        if code == 0 {\n            return;\n        }\n\n        let errno = unsafe { *libc::__error() };\n\n        match errno {\n            libc::EPERM => {\n                // This thread has been excluded from the QoS system\n                // due to a previous call to a function such as `pthread_setschedparam`\n                // which is incompatible with QoS.\n                //\n                // Panic instead of returning an error\n                // to maintain the invariant that we only use QoS APIs.\n                panic!(\"tried to set QoS of thread which has opted out of QoS (os error {errno})\")\n            }\n\n            libc::EINVAL => {\n                // This is returned if we pass something other than a qos_class_t\n                // to `pthread_set_qos_class_self_np`.\n                //\n                // This is impossible, so again panic.\n                unreachable!(\n                    \"invalid qos_class_t value was passed to pthread_set_qos_class_self_np\"\n                )\n            }\n\n            _ => {\n                // `pthread_set_qos_class_self_np`'s documentation\n                // does not mention any other errors.\n                unreachable!(\"`pthread_set_qos_class_self_np` returned unexpected error {errno}\")\n            }\n        }","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/stdx/src/thread/intent.rs#L180-L216","documentation":"On macOS, rust-analyzer manages thread priority exclusively through QoS (Quality of Service) APIs (`pthread_set_qos_class_self_np`). If setting the QoS class returns ENOTSUP/ENOTSCHED (errno stored), the thread has previously opted out of the QoS system — e.g. via `pthread_setschedparam`-style scheduling calls incompatible with QoS — and can no longer use QoS APIs. The code deliberately panics instead of returning an error to uphold the invariant that only QoS APIs are used for thread intent.","triggerScenarios":"Calling `set_current_thread_qos_class` on a thread whose scheduling was previously modified by a non-QoS API such as `pthread_setschedparam`, `thread_policy_set`, or manual scheduling; mixing `stdx::thread` intent APIs with platform-specific priority tweaks in the same thread.","commonSituations":"Developers integrating custom thread priority/scheduling code (real-time audio-style policies) alongside rust-analyzer's thread pool on macOS; embedding rust-analyzer in an app that adjusts thread policies on its worker threads.","solutions":["Stop using non-QoS scheduling APIs (`pthread_setschedparam` etc.) on threads managed by stdx::thread; rely on ThreadIntent/QoS only","Spawn a fresh thread that has never had its policy modified and use QoS intent APIs from the start","If you must use manual scheduling, do not attempt QoS calls afterward on that thread"],"exampleFix":"// before\npthread_setschedparam(pthread_self(), SCHED_FIFO, &param);\nstdx::thread::set_current_thread_qos_class(...).unwrap(); // panics\n// after\n// drop the manual scheduling call entirely\nstdx::thread::set_current_thread_qos_class(...).unwrap();","handlingStrategy":"validation","validationCode":"// Before managing intent, confirm the thread hasn't been policy-modified:\nlet class = libc::qos_class_self(); // probing is safe\nif class == libc::QOS_CLASS_UNSPECIFIED {\n    eprintln!(\"thread opted out of QoS; skip set_current_thread_qos_class\");\n} else {\n    stdx::thread::set_current_thread_qos_class(intent)?;\n}","typeGuard":null,"tryCatchPattern":"// Guard the process-level invariant during embedding:\nlet result = std::panic::catch_unwind(||\n    stdx::thread::set_current_thread_qos_class(ThreadIntent::Worker)\n);","preventionTips":["Never call pthread_setschedparam/thread_policy_set on stdx::thread-managed threads","Use ThreadIntent/QoS as the only priority mechanism on macOS","If manual scheduling is required, run it on separate threads from intent-managed ones"],"tags":["rust","macos","thread-priority","qos","panic"],"backgroundTag":"thread-qos-optout","analyzedSha":"e8f7e90aa3e7b26aa9a000200f606c1078da99ec","analyzedAt":"2026-09-03T21:08:06.959Z","contentChangedAt":"2026-09-03T21:08:06.959Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}