TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Ctrl-C

210 pointsby kclalmost 3 years ago

24 comments

xyzzy_plughalmost 3 years ago
This makes no sense. Ctrl-C is just a way to tell your terminal to send a SIGINT signal to the current process. How that process handles the signal is up to it! It&#x27;s by definition ignorable, as the author points out, but it&#x27;s not rocket science to handle it in a sane fashion even in a multi-threaded application. Modern languages make this trivial. The author makes it sound like some dark art but in reality you just have to read the manpages.<p>SIGINT is really designed for interactive applications. Most processes should simply treat it like a SIGTERM unless they have some sort of REPL. Unless you need graceful shutdown, most processes shouldn&#x27;t mask either signal. If they do, the polite thing is to unmask after receiving the first signal so subsequent signals immediately terminate.
评论 #32368262 未加载
评论 #32369259 未加载
评论 #32367927 未加载
评论 #32367488 未加载
评论 #32367626 未加载
评论 #32367830 未加载
评论 #32370757 未加载
untitaker_almost 3 years ago
I feel this. Signal handling in Python code is especially complicated. I&#x27;m not even talking about multithreading here (not like you get anything out of it anyway).<p>Python registers POSIX signal handlers, that upon SIGTERM&#x2F;SIGINT, set a flag. Next time the interpreter loop runs, the flag is checked before the next instruction is being run and the stack is unwinded.<p>When you call out to some C code, that C code may run for a long time. During that time, there is no interpreter loop actually looping. Therefore, all signals are ignored in principle while C code runs.<p>It&#x27;s possible for Python code to become uninterruptible while it is calling something like pthread_join.<p>See <a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;39930722&#x2F;how-do-i-catch-an-interrupt-signal-in-python-when-inside-a-blocking-boost-c-me" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;39930722&#x2F;how-do-i-catch-...</a><p>Then of course, you have that on top of all the other problems mentioned by the blogpost.
评论 #32372766 未加载
评论 #32370821 未加载
codethiefalmost 3 years ago
&gt; We don&#x27;t want our ctrl-c to leak memory. […] If you allocate a piece of memory, you need to store a pointer to that memory from the object graph, and both of those operations need to occur inside of a critical section. Otherwise, if you get interrupted right after the allocation, there won&#x27;t be any way to reach your memory and it will leak.<p>Maybe I&#x27;m missing something here but… so what? If at the end of your Ctrl+C signal handler you exit() as expected, then the OS will clean up your process&#x27;s memory anyway.
评论 #32367437 未加载
评论 #32367964 未加载
e63f67dd-065balmost 3 years ago
I&#x27;m having trouble judging what exactly the author wants here. My best reading is that he wants interactive programs to respond to SIGINT not by bailing out but by terminating the current task and returning to user input.<p>I&#x27;m having trouble, however, thinking of programs to which this applies. I just scrolled through my shell history, and the most common interactive program I&#x27;ve used in my history file is a debugger, which handles killing the active program correctly with no issues, followed by resource monitoring applications, shells, etc.<p>Can somebody tell me an example command-line application where there&#x27;s a high degree of interactivity but is also multithreaded, has DB consistency guarantees, network requests in-flight, etc? I&#x27;m genuinely having trouble thinking of anything that&#x27;s not a REPL or vim&#x2F;emacs.
评论 #32368110 未加载
评论 #32372163 未加载
dmarinusalmost 3 years ago
After decades of experience I learned to use ctrl-\ (break) or ctrl-z and then kill -9 %1. Hope this helps someone.
评论 #32367199 未加载
评论 #32367362 未加载
评论 #32368310 未加载
fmajidalmost 3 years ago
I don’t have any expectations of a program doing an orderly shutdown and trying to avoid corrupting files on disk when interrupted by Ctrl-C.
AshamedCaptainalmost 3 years ago
Laugh all you want, but this is is precisely why I like &quot;old-fashioned&quot; asynchronous exceptions (the ones which unwind the stack), and ensure most programs are ready to handle a clean stack unwind at practically any point inside the program (e.g. asynchronous-unwind-tables).
评论 #32367290 未加载
teddyhalmost 3 years ago
This is a <i>far</i> better resource on the subject:<p><i>Proper handling of SIGINT&#x2F;SIGQUIT</i>: <a href="https:&#x2F;&#x2F;www.cons.org&#x2F;cracauer&#x2F;sigint.html" rel="nofollow">https:&#x2F;&#x2F;www.cons.org&#x2F;cracauer&#x2F;sigint.html</a>
jesprenjalmost 3 years ago
Even though it makes sense from the name, SIGINT, to interrupt, I&#x27;ve rarely seen console software &quot;return control&quot; to the user when the signal is received.<p>What I&#x27;ve mostly seen in programs is a clean exit from the running application, if live user input is not intended to be used. Clearing a line or something similar like redrawing the terminal (that&#x27;s mostly Ctrl-L though) is what interactive programs do, let&#x27;s say shells or ncurses UI programs.<p>Whenever I made some hobby scripts that exit cleanly when receiving a SIGINT, I&#x27;ve made a global counter of interrupts. When SIGINT is received, the counter is incremented, which tells the main loop to stop as soon as possible. But if this counter exceeds three signals, the application would exit immediatley. This may not be ideal, but CTRL-C CTRL-C CTRL-C is easier than kill -9 `pgrep a.out`.<p>Like the top comment says, expecting a concrete and general behaviour on different types of software for such a broad signal doesn&#x27;t gain wide approval.<p>What &quot;return of control&quot; did the author mean, on what kinds software?
评论 #32370539 未加载
jillesvangurpalmost 3 years ago
A lot of multi threaded server software handles ctr+c just fine. A lot of Java based server software have a shutdown hook, which is something that you can easily add to any jvm based program because it is part of the standard library. If you use Spring Boot, for example, it has one and it will start shutting down your Spring Context and call any destroy functions on DestroyingBean implementations, which is how you can add your own shut down logic in Spring.<p>Good explanation here of shutdown hooks: <a href="https:&#x2F;&#x2F;www.baeldung.com&#x2F;jvm-shutdown-hooks" rel="nofollow">https:&#x2F;&#x2F;www.baeldung.com&#x2F;jvm-shutdown-hooks</a>
M9HF8wwiaAdZKEZalmost 3 years ago
As far as I can tell, this appears to be confusing Ctrl+C (SIGINT, which terminates a process, and is usually <i>not</i> restartable), with Ctrl+Z (SIGTSTP, which pauses a process, and is thus restartable).<p>The only software I can think of that could &quot;restart&quot; after a Ctrl+C is usually daemons or other long-lived processes (which already need to be able to &quot;restart&quot; after any kind of shutdown and thus have significant amounts of code dedicated to serializing and unserializing their internal state).<p>TFA even goes so far as to talk about memory leaks - which are completely irrelevant when your process is about to exit anyway!
评论 #32368953 未加载
评论 #32369096 未加载
评论 #32372227 未加载
pdwalmost 3 years ago
I&#x27;m confused. Which software is he talking about? I can&#x27;t think of any program screwing up Ctrl-C in a bad way.
评论 #32368455 未加载
nrabulinskialmost 3 years ago
I don’t think I’ve ever encountered a CLI application which I couldn’t kill with ^C other than defunct processes
评论 #32367549 未加载
评论 #32367391 未加载
评论 #32369112 未加载
ghowardalmost 3 years ago
Surprisingly, it <i>is</i> possible to do exactly what the author wants. I know because I&#x27;ve done it. However, it <i>is</i> as complicated as the author says it is.<p>The project in question is my `bc` [1].<p>Until version 3.0.0 [2], it used a &quot;yield&quot; architecture: every loop it could enter had a check for a signal. This got tedious, so I decided to make the jump to instant-ish reset.<p>I was lucky in several ways. First, `bc` is a really good program to reset; you just stop it executing, wipe all data away, and ask for more input with a blank slate. Second, it is single-threaded.<p>Nevertheless, it was still really difficult, especially to have no memory leaks.<p>First, I had to learn how to use `sigsetjmp()` and `siglongjmp()`. Yep, that was how I was going to do this. Once I learned, I implemented a stack of `sigjmp_buf`&#x27;s. Then, when a signal happens, each individual `sigjmp_buf` is used. This allowed me to properly free memory on the way.<p>In essence, if a function had allocated memory, then it would push a `sigjmp_buf` on the stack, and then when a `siglongjmp()` happened, execution would go to a label where that memory would be freed before continuing the jump series.<p>Then I implemented signal locks. It is safe to `siglongjmp()` out of signal handler, as long as it didn&#x27;t interrupt code that was non-async-signal-safe. So I used signal locks for that, and when &quot;unlocking&quot; the lock, it would check for a signal and jump. And if the signal handler sees a lock, it just sets a flag and returns.<p>Then I had to go through my codebase and protect every bit of non-async-signal-safe code with locks. It was tedious, but the result is fantastic.<p>Edit: I forgot to add that there is more information at [3] and [4].<p>Nowadays, I&#x27;m working on a threaded build system, and when it gets SIGINT, it sends a message to threads to stop as soon as their children are done. If it receives a second, it just exits.<p>So yeah, every application is different, but it <i>is</i> possible.<p>[1]: <a href="https:&#x2F;&#x2F;git.yzena.com&#x2F;gavin&#x2F;bc" rel="nofollow">https:&#x2F;&#x2F;git.yzena.com&#x2F;gavin&#x2F;bc</a><p>[2]: <a href="https:&#x2F;&#x2F;git.yzena.com&#x2F;gavin&#x2F;bc&#x2F;src&#x2F;branch&#x2F;master&#x2F;NEWS.md#3-0-0" rel="nofollow">https:&#x2F;&#x2F;git.yzena.com&#x2F;gavin&#x2F;bc&#x2F;src&#x2F;branch&#x2F;master&#x2F;NEWS.md#3-0...</a><p>[3]: <a href="https:&#x2F;&#x2F;git.yzena.com&#x2F;gavin&#x2F;bc&#x2F;src&#x2F;branch&#x2F;master&#x2F;manuals&#x2F;development.md#async-signal-safe-115-signal-handling" rel="nofollow">https:&#x2F;&#x2F;git.yzena.com&#x2F;gavin&#x2F;bc&#x2F;src&#x2F;branch&#x2F;master&#x2F;manuals&#x2F;dev...</a><p>[4]: <a href="https:&#x2F;&#x2F;git.yzena.com&#x2F;gavin&#x2F;bc&#x2F;src&#x2F;branch&#x2F;master&#x2F;manuals&#x2F;development.md#user-content-error-handling" rel="nofollow">https:&#x2F;&#x2F;git.yzena.com&#x2F;gavin&#x2F;bc&#x2F;src&#x2F;branch&#x2F;master&#x2F;manuals&#x2F;dev...</a>
评论 #32370459 未加载
mlhpdxalmost 3 years ago
Maybe I’m missing the point, but this (essentially random example) is multithreaded (asynchronous) and gracefully handles ctrl-c. Yes, it’s a high level language that makes it easy, I guess.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;mlhpdx&#x2F;SimplestLoadBalancer" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;mlhpdx&#x2F;SimplestLoadBalancer</a>
pixelbeat__almost 3 years ago
I agree that this is an awkward but very desirable property for a system to have.<p>I was calling this &quot;responsive idempotence&quot; when discussing how the GNU coreutils are tested:<p><a href="https:&#x2F;&#x2F;www.pixelbeat.org&#x2F;docs&#x2F;coreutils-testing.html" rel="nofollow">https:&#x2F;&#x2F;www.pixelbeat.org&#x2F;docs&#x2F;coreutils-testing.html</a>
rmetzleralmost 3 years ago
Currently I find kubectl often don&#x27;t really respond for CTRL-C and also can&#x27;t be removed with kill -9 on MacOS.
CoffeeCollectoralmost 3 years ago
What is a “tight C loop”?
评论 #32368388 未加载
aumerlealmost 3 years ago
Write your program around an event loop which if its an interactive program it already has. And read man signalfd.
g5095almost 3 years ago
&quot;More often than not I find myself having to kill the running process from an external app, such as the shell, after first figuring out what the process ID is.&quot;<p>Short cut here, ctrl-z to background the process, then kill -9 %1 to kill the first job (type jobs for the numbers)
rgbrgbalmost 3 years ago
Would love if prompts fixed this so it was easy to implement in my CLI app: <a href="https:&#x2F;&#x2F;github.com&#x2F;terkelg&#x2F;prompts&#x2F;issues&#x2F;252" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;terkelg&#x2F;prompts&#x2F;issues&#x2F;252</a>
taf2almost 3 years ago
I prefer when programs listen for SIGQUIT… it makes more sense that this would be used to quit a process then SIGINT - IMO …
ruslanalmost 3 years ago
Just wonder if author is aware of SIGSTOP&#x2F;SIGCONT that allows to pause&#x2F;resume any process gracefully ? Both signals can be caught and handled.<p>Crtl-C (SIGINT), as far as I know, was used to &quot;gracefully terminate&quot; interactive process from day zero of Unix. I cannot find any use in that of what author proposes: suspend execution by sending SIGINT, but then what ? Get to some process built-in debugging shell ? Isn&#x27;t that what GDB was made for ?
评论 #32373423 未加载
ape4almost 3 years ago
I thought this was going to be another C++ replacement - actually not a bad name.