# Graceful Shutdown and Cleanup The server will run endlessly, waiting for requests asynchronously. Exactly, endlessly until we press Ctrl+C. But what if we want to shut it down cleanly? There are no ways to clean properly the `worker` `id` `thread`. We have to implement `Drop` to make sure the threaads are cleaned up when the memory is dropped! ## Implementing `Drop` on `ThreadPool` ```rust impl Drop for ThreadPool { fn drop(&mut self) { for worker in &mut self.threads { // Vectors is already a collection that can be iterated // just use it as mutable reference so that iterator is also mutable println!("Joining worker: {}", worker.id); worker.thread.join().unwrap(); // This does not compile, thread does a move of ownership of thread, which does not implement copy // We can't move from a borrowed reference } } } ``` Instead we have to change thread to be `Option<>` of a thread instead. ```rust struct Worker { id: usize, thread: Option>, } // Now we have to update the new: Worker {id, thread: Some(thread)} // Then we update the drop function if let Some(thread) = worker.thread.take() { thread.join().unwrap(); } ``` ## Signaling Threads to Stop It joins, but it still does not stop looking for jobs. We need for the worker to listen for different types of actions (Job, Terminate,...), instead we use an enum to signal different actions: ```rust enum Message { NewJob(Job), Terminate, } ``` Then make the `execute` func to relay messages instead of only jobs, same for the channels and the `Worker` to interpret them: ```rust pub struct ThreadPool { workers: Vec, sender: mpsc::Sender, } // --snip-- impl ThreadPool { // --snip-- // Execute now should send the enum with the added closure pub fn execute(&self, f: F) where F: FnOnce() + Send + 'static, { let job = Box::new(f); self.sender.send(Message::NewJob(job)).unwrap(); } } // --snip-- impl Worker { fn new(id: usize, receiver: Arc>>) -> Worker { let thread = thread::spawn(move || loop { let message = receiver.lock().unwrap().recv().unwrap(); // Change closure to match message types and perform as expected match message { Message::NewJob(job) => { println!("Worker {} got a job; executing.", id); job(); } Message::Terminate => { println!("Worker {} was told to terminate.", id); break; } } }); Worker { id, thread: Some(thread), } } } ``` Then the `Drop` on the `ThreadPool` to use 2 loops, one for sending the terminate, and the other to join them. 2 Loops because, sending a message does not guarantee that the worker we are on will receive it. Thus we might be waiting on another thread and the current one will not be terminated. ```rust impl Drop for ThreadPool { fn drop(&mut self) { // Send a terminate message to all workers just in case for _ in &self.threads { self.sender.send(Message::Terminate).unwrap(); } for worker in &mut self.threads { // Vectors is already a collection that can be iterated // just use it as mutable reference so that iterator is also mutable println!("Joining worker: {}", worker.id); if let Some(thread) = worker.thread.take() { thread.join().unwrap(); } } } } ```