#Non blocking threads to run in the background.

12 messages · Page 1 of 1 (latest)

quartz solar
#
pub static LISTENER: SyncOnceCell<RwLock<SoliloquyListener>> = SyncOnceCell::new();

pub static THREADPOOL: SyncOnceCell<RwLock<ThreadPool>> = SyncOnceCell::new();


   fn set_new_pool(handle: Vec<JoinHandle<()>>){

        let threads = ThreadPool(handle);

        THREADPOOL.set(RwLock::new(threads)).unwrap();

    }

 pub fn raise_listener_status_loop(){

        let handle = thread::spawn(||{

            let listener = LISTENER.get()
                                                 .unwrap()
                                                 .read()
                                                 .unwrap();
            while !listener.halt_scheduled{

                thread::sleep(Duration::from_millis(250));
            }

        });

        match THREADPOOL.get(){
            Some(pool) => pool.write()
                                                .unwrap()
                                                .0
                                                .push(handle),

            None => ThreadPool::set_new_pool(vec![handle]),
        };
    } 
}```


All the functions are associated functions..

Everything here is in a lib, not a binary.

What I am trying to do here is for every thread I push to the pool not to block the binary's main thread, but to keep it alive until the while conditions in all the threads (only one is implemented atm) evalute to true. The thread should then run some cleanup code that will be placed below the loop and exit. Once all the threads in the pool exit, the whole program should exit.

Instead, debugging shows that one iteration of the loop runs and then the process exits. Yes, LISTENER's `halt_scheduled` field is set to false. I'm pretty sure I'm doing this quite wrong as this is my first stab at this. Any help?
tranquil hazel
#

I don't really understand what issue you're describing, but you've got a TOCTTOU bug here by calling get then set on a OnceCell; that is not an appropriate use of that API. OnceCell documentation page should show how to use it correctly; should actually simplify your code dramatically.

#

You may want to show the loop you're talking about to get help with that issue, although I guess it could be related to this OnceCell misuse.

quartz solar
#

this issue is that I have some logic in a binary calling this library. The LISTENER static must be placed into a state in which it must run for some indeterminate time getting, processing, and responding to input. There is a function call elsewhere in the code that will schedule LISTENER to stop listening by setting halt_scheduled to be true. the while loop in the first few lines of raise_listener_status_loop reads this state and will run some cleanup code after it is found to be true.

#

I will look into the points you raised. I'm quite new to rust's way of handling global state.

quartz solar
tranquil hazel
#

Yes. OnceCell API prevents a really bad issue like UB here but it's still semantically not quite right because handle wouldn't be appended to the list in case of a race

quartz solar
#

Doesn't the RwLock prevent that? (i've switched it to a mutex now to ensure that None is returned only when the the cell is uninitialized & there are no pending calls to initialize it). It still is not working.

#

Also, i'm not making multiple calls to initialize the cell at this time There is only one.

#

I understand that i'm not calling join, nor can I without mutating the static. I also don't really want a join as that blocks the main thread. I need a non blocking operation. which makes me feel I need some other primitive. Maybe that's in one of the async runtime crates?

#

I'm also really just too new with rust to really comprehend the ramifications of one crate over the other, nor do I yet grasp their scope.

#

wait, oh my god, should I be takeing the struct out, mutating it, then returning it to the global scope?