Skip to content

windows-services, using the service parameter in the closure passed to run with standard library threads. #3694

@adedomin

Description

@adedomin

Summary

I was experimenting with the latest release (0.25.0) of windows-services, but was struggling on how to use the service parameter passed to the callback. Rust rightfully points out I am leaking that parameter when I store the JoinHandle of the thread running my service code (so I can join it later). I saw the example but now I'm wondering if this is possible using the standard library's threads.

the compile error:

Compiling example-winsvc v0.1.0 (C:\Users\prussian\source\example-winsvc)
error[E0521]: borrowed data escapes outside of closure
  --> src\main.rs:10:21
   |
5  |         let mut thread = None;
   |             ---------- `thread` declared here, outside of the closure body
...
8  |             .run(|svc, comm| match comm {
   |                   --- `svc` is a reference that is only valid in the closure body
9  |                 windows_services::Command::Start if thread.is_none() => {
10 |                     thread = Some(s.spawn(|| {
   |                     ^^^^^^ `svc` escapes the closure body here

For more information about this error, try `rustc --explain E0521`.
error: could not compile `example-winsvc` (bin "example-winsvc") due to 1 previous error

Crate manifest

[package]
name = "example-winsvc"
version = "0.1.0"
edition = "2024"

[dependencies]
windows-services = "0.25"

Crate code

use windows_services::{Service, State};

fn main() {
    std::thread::scope(|s| {
        let mut thread = None;
        if Service::new()
            .can_stop()
            .run(|svc, comm| match comm {
                windows_services::Command::Start if thread.is_none() => {
                    thread = Some(s.spawn(|| {
                        println!("Hello, World!");
                        svc.set_state(State::Stopped);
                    }));
                }
                windows_services::Command::Stop => {
                    if let Some(jh) = thread.take() {
                        jh.join();
                    }
                }
                _ => (),
            })
            .is_err()
        {
            eprintln!("not running as service");
        };
    });
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions