How to stop ( loop forever )

Clippy is warning about my code here:

    while stop {
        // Program is terminating, loop forever.
        std::thread::sleep(std::time::Duration::from_millis(100));
    }

the message:

    |
145 |         while stop {
    |               ^^^^
    |
    = note: this may lead to an infinite or to a never running loop
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.96.0/index.html#while_immutable_condition
    = note: `#[deny(clippy::while_immutable_condition)]` on by default

For now I have just suppressed it with

#[allow(clippy::while_immutable_condition)]

but I was wondering is there is a more elegant solution. Also, is there a simpler way of sleeping forever?

if stop {
    loop { std::thread::park(); }
}

I like the if stop idea, actually I had thought of that myself, then forgot about the idea ( which is typical... ).

I did read about park, but this bit seemed a little alarming:

"it may abort the process if the implementation encounters some rare errors"

I don't want the process to abort, that would be bad.

Whatever that error condition is (I don’t actually know), it’s likely to be something that breaks other thread-related things even if you avoid calling park() yourself.

For instance, a panic [note: now it's process abort] occurs if the TLS key used to store the thread info cannot be created, if a new thread id cannot be created, if the creation of a parking primitive fails, if the current time is not available and if the parking operation fails.

(`thread::park` causes undefined behaviour on panic · Issue #102398 · rust-lang/rust · GitHub)

Your existing code will likely panic if there are time problems, too.

if stop {
    std::thread::sleep(std::time::Duration::MAX);
}

...gives you about 585 billion years, which is for practical purposes: Forever.

It seems like clippy is warning you about something reasonable. What would cause stop to be true in your code and why is the infinite loop necessary?

The module implements atomic updating of files, with a thread that does the commits as a background thread, so there is a kind of pipeline. On shutdown, the aim is for commits that have happened (been passed to the background thread) to be completed, but a line has to be drawn somewhere, so new commits are not allowed to happen, which is what the stop flag is for. When the producer sees the flag is set, it needs to just stop and do nothing more ( in particular it should not inform its client that anything has completed, as that would be misleading ).

So anyway, the code was perfectly fine, but clippy (quite reasonably) warned about an infinite loop, which in this rather unusual case is what is needed.

Why don't you use an MPSC channel to send the input to the processing thread. And on termination just drop the Sender and let the Receiver just finish processing the queue?

Well if I understand you correctly, that would stop new commits being sent to the background thread, but the producing thread still needs to do "something", and the simplest option is to do "nothing", that is "stop". Another approach would be to return an error "could not save changes due to process terminating", but given that the process is terminating and there is no certainty (or even likelihood) of the error (or whatever you want to call it) ever being transmitted and received, simply stopping seems simplest to me.

The basic thing I am trying to do here is to terminate the process ASAP (and as simply as possible), but not losing updates that have already been logically committed.

In situations such as this you probably don't want an infinite loop. It implies that you can never join the thread that hit the loop, but you should try to always join threads that you spawn (to propagate panics). Part of your clean shutdown should involve joining the background thread that does the writes. When you are in the shutdown state, producers should not be allowed to send to the consumer.

This isn't a clean shutdown, it is a shutdown "as fast as possible" while not losing committed data. You could have a slow shutdown you run first, waiting for existing work to finish but not accepting new work (or even I suppose accepting new work), that would be a different level. In that case (provided it didn't run into some time limit) the stop condition would never be encountered.