windows-serviceを使用して actix Web アプリを実行しようとしています。優れた API を提供し、ほとんどの場合動作します。サービスを問題なく開始できます。ただし、サービスを停止しようとすると、次のエラーが表示されます: Error 109: The pipe has been ended
(ただし、サービスは停止します)。
私は主に に提供されている例を使用してwindows-service
いますが、関連するコードは次のとおりです (コンテキストとすべてのラッパー関数については、https://github.com/mullvad/windows-service-rs/blob/master/examples/を確認してください)。 ping_service.rs ):
pub fn run_service() -> Result<()> {
fn hi() -> impl actix_web::Responder {
"Hello!\r\n"
}
let sys = actix_rt::System::new("test");
actix_web::HttpServer::new(move || {
actix_web::App::new()
.route("/", actix_web::web::get().to(hi))
})
.bind("0.0.0.0:3000").unwrap()
.start();
let event_handler = move |control_event| -> ServiceControlHandlerResult {
match control_event {
ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,
ServiceControl::Stop => {
actix_rt::System::with_current(|s| s.stop());
ServiceControlHandlerResult::NoError
}
_ => ServiceControlHandlerResult::NotImplemented,
}
};
let status_handle = service_control_handler::register(SERVICE_NAME, event_handler)?;
status_handle.set_service_status(ServiceStatus {
service_type: SERVICE_TYPE,
current_state: ServiceState::Running,
controls_accepted: ServiceControlAccept::STOP,
exit_code: ServiceExitCode::Win32(0),
checkpoint: 0,
wait_hint: Duration::default(),
})?;
sys.run().unwrap();
status_handle.set_service_status(ServiceStatus {
service_type: SERVICE_TYPE,
current_state: ServiceState::Stopped,
controls_accepted: ServiceControlAccept::empty(),
exit_code: ServiceExitCode::Win32(0),
checkpoint: 0,
wait_hint: Duration::default(),
})?;
Ok(())
}
を に入れるとSystem::stop
、thread::spawn
別のエラーが発生します: The service did not return an error. This could be an internal Windows error or an internal service error
。この場合、サービスは停止しません。
いくつかのログを記録しましたが、コードが を通過したようには見えませんsys.run().unwrap()
。これは奇妙です。
何かご意見は?これまで Windows Service API を使用したことがないため、何をしているのかよくわかりません。
編集
主な問題が何であるかを理解しました。サービスを停止する前に、サービスが停止したことを Windows に通知する必要があります。私はそれを機能させるために不格好な方法をまとめました:
std::thread::spawn(move || {
loop {
if shutdown_signal.load(Ordering::Relaxed) {
status_handle.set_service_status(ServiceStatus {
service_type: SERVICE_TYPE,
current_state: ServiceState::Stopped,
controls_accepted: ServiceControlAccept::empty(),
exit_code: ServiceExitCode::Win32(0),
checkpoint: 0,
wait_hint: Duration::default(),
}).unwrap();
actix_rt::System::current().stop();
break;
}
}
});
sys.run().unwrap();
// ...
ここshutdown_signal
でAtomicBool
、イベント ハンドラで I を true に設定します。代わりに、何らかの方法でこれを行うことができるかどうかを確認しますactix_rt
。