If Rust doesn't have exceptions, what happens on Ctrl+C?

Rust does not have exceptions. To indicate issues, it instead relies on strongly typed return values called Result that are either in an Err state or Ok state. Part of programming in Rust is learning that you need to explicitly handle both of these cases, even if common cases are handled by try! and ?.

That's sort of fine for inspecting the return values of functions. But what happens if an error occurs outside of a function boundary?

To illustrate what I expect to happen, consider this Python code:

import time

seconds_so_far = 0.0
delay = 0.25

while True:
    print('{}'.format(seconds_so_far))
    seconds_so_far += delay
    time.sleep(delay)

If I save that code as seconds_so_far.py and run it in cmd.exe or a Terminal, I am quite used to something like the following appearing:

$ python seconds_so_far.py 
0.0
0.25
0.5
0.75
1.0
1.25
1.5
^CTraceback (most recent call last):
  File "seconds_so_far.py", line 9, in <module>
    time.sleep(delay)
KeyboardInterrupt

The ^C indicates that I've pushed Ctrl+C together in my bash shell. Eventually to operating system will send SIGINT to the Python interpreter, which will then raise the KeyboardInterrupt exception. If this isn't explicitly handled by the programmer, then Python will terminate.

Let's try writing a similar sort of thing in Rust. We'll use cargo to get us going.

$ cargo new --bin seconds_so_far

Once the project is generated, open seconds_so_far/src/main.rs in a text editor and try replacing its contents with the following:

use std::{thread, time};

fn main() {  
    let mut seconds_so_far = 0.0;
    let delay = time::Duration::from_millis(250);

    loop {
        println!("{}", seconds_so_far);
    thread::sleep(delay);
    seconds_so_far += 0.25;
    }
}

Let's try and run the project to see what will happen when we interrupt it once it's going..

$ cargo run
   Compiling seconds_so_far v0.1.0 (file:///home/tim/Documents/Articles/Seconds%20So%20Far/seconds_so_far)
     Running `target/debug/seconds_so_far`
0  
0.25  
0.5  
0.75  
1  
1.25  
^C

Wow. Severe anti-climax. Pretty much what one might expect really.. the program exited.

Interestingly from me (as a Python programmer) this doesn't give me much information to go by if I wanted to handle the signal in my code.

Looking at the best issue ticket I could find, it looks like signal handling in the stdlib is currently up in the air. It seems that the Rust team is waiting for third party libraries to play around with APIs and then whatever settles will make its way into the language.