To fix the Deno watch mode issue, I researched both Deno and Node.js. I want to use Node.js's approach but implement it in Rust for Deno.
Rust doesn't have a built-in process.kill() function like JavaScript to send signals, but we can simulate this using channels. When creating a channel, we get a sender (Tx) and a receiver (Rx) that work together, which helps avoid race conditions.
I created a pull request (PR) that uses a channel to allow the worker process to inform the watcher process when the INT signal is handled, instead of letting the watcher process handle and ignore it.
Here’s how I set it up:
// Create a channel before starting the worker process
let (ctrl_c_tx, mut ctrl_c_rx) = tokio::sync::mpsc::unbounded_channel::<()>();
let watcher_communicator =
Arc::new(WatcherCommunicator::new(WatcherCommunicatorOptions {
// Pass the sender to the worker
ctrl_c_tx: ctrl_c_tx.clone(),
}));
impl WatcherCommunicator {
// Public function to inform the watcher process
pub fn handle_ctrl_c(&self) -> Result<(), SendError<()>> {
self.ctrl_c_tx.send(())
}
}
I also removed the INT handler from the watcher process and replaced it with the channel's receive handler:
// _ = deno_signals::ctrl_c() => {
_ = ctrl_c_rx.recv() => {
This approach requires a better understanding of how the signal API is implemented in Deno. The Signal.rs file shows how the Deno.addSignalListener() or process.on(signalName, callback) API works. I'm still looking for the right place to trigger the channel sender without breaking existing behavior.
Implementing this feature has been the most challenging task I've faced recently. Three months ago, I had never written a line of Rust, but now I'm working on something significant written in Rust. I can't believe how far I've come since starting my open-source journey. I want to thank my professor, humphd, for encouraging everyone in class to get involved in the open-source community. Everyone has grown so much this semester; this has been the best course I've taken.
Top comments (0)