{"record":{"id":"e45cd482e7ba4446","repo":"tauri-apps/tauri","slug":"unable-to-kill-native-webdriver-server","errorCode":null,"errorMessage":"unable to kill native webdriver server","messagePattern":"unable to kill native webdriver server","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tauri-driver/src/server.rs","lineNumber":186,"sourceCode":"\n#[tokio::main(flavor = \"current_thread\")]\npub async fn run(args: Args, mut _driver: Child) -> Result<(), Error> {\n  #[cfg(unix)]\n  let (signals_handle, signals_task) = {\n    use futures_util::StreamExt;\n    use signal_hook::consts::signal::*;\n\n    let signals = signal_hook_tokio::Signals::new([SIGTERM, SIGINT, SIGQUIT])?;\n    let signals_handle = signals.handle();\n    let signals_task = tokio::spawn(async move {\n      let mut signals = signals.fuse();\n      #[allow(clippy::never_loop)]\n      while let Some(signal) = signals.next().await {\n        match signal {\n          SIGTERM | SIGINT | SIGQUIT => {\n            _driver\n              .kill()\n              .expect(\"unable to kill native webdriver server\");\n            std::process::exit(0);\n          }\n          _ => unreachable!(),\n        }\n      }\n    });\n    (signals_handle, signals_task)\n  };\n\n  let address = std::net::SocketAddr::from(([127, 0, 0, 1], args.port));\n\n  // the client we use to proxy requests to the native webdriver\n  let client = Client::builder(TokioExecutor::new())\n    .http1_preserve_header_case(true)\n    .http1_title_case_headers(true)\n    .retry_canceled_requests(false)\n    .build_http();\n","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/tauri-apps/tauri/blob/52e4b6e71d8632a7e648f866c442e287ecddee34/crates/tauri-driver/src/server.rs#L168-L204","documentation":"Shutdown-time panic in tauri-driver: on SIGTERM/SIGINT/SIGQUIT the signal task calls _driver.kill().expect(\"unable to kill native webdriver server\") on the native WebDriver child process. kill() fails when the child has already exited (it crashed or was killed elsewhere, or a second signal raced the first), so the handler panics instead of exiting cleanly.","triggerScenarios":"Sending Ctrl+C/SIGTERM when the native WebDriver already died — e.g. it crashed during the test run — or a second termination signal arriving while the first shutdown is still in progress.","commonSituations":"Test session ends after WebKitWebDriver/msedgedriver crashed mid-run; CI sending SIGTERM then quickly SIGKILL; supervisors double-signaling tauri-driver.","solutions":["Upgrade tauri-driver — killing an already-exited child should be tolerated; check release notes for the fix","Keep the native driver healthy during the run: watch its stderr and fix the underlying crash (often missing WebKitGTK libs)","Send one termination signal and allow a grace period before escalating","In CI wrappers, treat a non-zero tauri-driver exit during shutdown as non-fatal when the tests themselves already passed"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Send a single termination signal and wait for shutdown before escalating","Watch the native driver's stderr during runs so you fix crashes before shutdown races them","In CI wrappers, ignore tauri-driver's exit status when tests already passed","Track tauri-driver updates that tolerate killing an already-exited child"],"tags":["webdriver","signal","shutdown","process"],"backgroundTag":"process-kill-failed","analyzedSha":"52e4b6e71d8632a7e648f866c442e287ecddee34","analyzedAt":"2026-08-20T13:59:20.734Z","contentChangedAt":"2026-08-20T13:59:20.734Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}