CTRL-C doesn't work to end endless loop from book

Hi Friends.

I'm learning Rust from the online Rust book to write a compiler. Anyways I can't seem to get CTRL-C to work correctly to end the program and close the loop, as per the instructions in the book.

The relevant chapter: Control Flow - The Rust Programming Language

The Relevant code:

fn main() {
    loop {
        println!("again!");
    }
}

I'm running cargo run it compiles, and runs, and just loops.

I'm running on an M2 MAX Macintosh.

Anyways I'd love to know what I can do to make this work properly. I'll even submit a PR to the book to change the chapter to reflect how to use CTRL-C.

Thanks new friends!

-kow

How are you running the code, I’m presuming something like cargo run from terminal?

1 Like

Try using the ⌘-C :grin:

3 Likes

yes. I'm running it using cargo run. If I run the binary directly from the command line the result is the same. infinite loop. If I build a release binary, and run that, then the problem persists.

That would be copy. That copies things.

Are you sure you didn't change the default behavior of ^Control?

https://www.reddit.com/r/MacOS/comments/17fpv1h/issue_with_ctrlc_in_the_terminal

It may be that the printing is keeping the terminal too busy to process the ^C. Apple’s Terminal is relatively slow at actually drawing large amounts of text. If this is a problem, inserting a sleep in your program (even just a millisecond), or using a different terminal program, will help.

2 Likes

100% sure I did not do that. It works everywhere else. in other terminals and when using other programs that loop.

So, interestingly. It looks like CTRL-C works in other terminals when using Rust, but not in the terminals I was using. In particular Apple's built in terminal terminates correctly. Panic's terminals' aren't working right though.

Thanks for your help everyone!

1 Like

My post isn't intended to be the answer to your question, but you can encounter similar behaviors in response to Control+C in other situations.

Control+C terminates all the running foreground processes for a specific progress group, therefore the SIGINT signal is received by them all. But: when you have a process that starts another child process, the parent process waits for the child process to finish and checks, how the child process has handled it's SIGINT. When the child process was terminated by this signal, then the parent process will be terminated, too ( in case you do not handle it otherwise via an own signal handler).

If the child process handles SIGINT in another way (e.g. Ctrl+C is handled as some sort of "copy" or as a cancellation of a command within this child process or (...)), then the parent process recognizes that SIGINT wasn't intented to be termination signal and does not terminate. This is called WCE (wait and cooperative exit). Signal handling is a very complex field in systems programming, sometimes trying to understand it can drive you nuts. Especially Ctrl+C and Ctrl+\ are sometimes pitfalls. To terminate a process or process group with grace, SIGTERM is the better alternative most of the time.

2 Likes

This is so interesting. I'd love to know more about this topic in depth. I'm sure there is documentation somewhere that talks about all the types of signals that a program can return, and what they mean.

Thanks for adding your comment.

I'm glad that I could clarify some issues.

I always recommend these books about Linux System Programming:

  • The Linux Programming Interface by Michael Kerrisk
  • Hands-On System Programming with Linux by Kaiwan N Billimoria
  • Advanced Programming in the UNIX Environment by W. Richard Stevens & Stephen A. Rago

With a little understanding of C programming you get all you want to know. Maybe you will find them as free books/PDFs on the web.

This page goes deeper into the WCE stuff

Cheers !

1 Like

I recommend you to watch this talk: https://youtube.com/watch?v=zhbkp_Fzqoo

1 Like

Yeah, this video is great stuff. Do not miss it!