got a lot of great answers to "how is the shell involved in handling Ctrl+C" to the effect of one of:
- "the shell is responsible for sending a SIGINT"
- "the shell takes input from the terminal emulator and relays it to the program"
- "it must be handled by the layer above the program, which is the shell"
and while none of those is true, they feel like they totally _could_ be true in a different world. It feels hard to explain why it might be useful to have a more "accurate" mental model
it feels like there's this mental model a lot of people have for the terminal which is a little like this (with some more stuff about signals etc)
and it's not "true" that the shell is in between the terminal emulator and programs in this way but it feels more compelling to me in some ways than the reality.
it makes explaining how the terminal works a little weird — I don't want to teach a “wrong” mental model just because it feels simpler (that seems silly), but also the "correct” mental model feels kind of overly complicated and not worth explaining because there's not obviously a lot of real-world value to learning it
not really looking for advice, just thinking out loud
(3/?)
@b0rk correct answer - it isn't? (half-guessing)
@b0rk I think it's necessary to know some of this if you want to implement a raw mode program that terminates "safely"? But I guess that's specialized these days. I've certainly seen it done "wrong".
@b0rk The best way to get it right is to implement it I believe. But I personally found it difficult to follow when things are getting to certain level of complexity. But still the mental model is there, and when I getting deeper in some context of implementation I remembering the details surrounding it.
Maybe invert the explanation, start with the terminal driver, cooked vs raw, etc?
@rk yeah I mean it's totally possible to explain all that stuff but... why should someone care? how does it help you get stuff done? it feels like a much more complicated mental model than "terminal emulator -> shell -> process" and it's not 100% obvious to me what value provides (other than being "correct" haha)
@b0rk @rk I suppose if there are important corner cases where the simpler mental model predicts the wrong behavior, and the more detailed model gets it right, that might be a reason to prefer the complex one.
But (as a person who has read the terminal drivers and understands things like process groups in signal delivery) I'm not sure I can think of any? A simpler model might be fine if you get the deets right.
@pulkomandy @rk it is true but then it raises a lot of confusing questions about what the role of the shell is exactly and how that all works (and honestly I find the answers to those questions very hard to summarize in a clear way, like “well the terminal driver has a foreground process group, and shell is in charge of managing what the foreground process is”)
feels bad to spend so much talking about what a “foreground process group” is because it's sort of an obscure concept generally
@buherator totally, the reason i'm interested in talking about the terminal's internals is that I think the abstractions are extremely leaky, like a lot of the basic things ("Ctrl+C”, "editing text") behave very differently depending on the situation and it's hard to understand why without looking under the surface a bit
@b0rk What is the correct version? Is the shell at the same level as the (other) programs? Or is the shell a tiny bit special here?
@bartavi it's something like this but this diagram doesn't do a great job of describing the shell's role on its own (or what the terminal driver does)
@b0rk @bartavi i like this image more because it also shows that the foreground process is not necessarily a shell. It can be anything, like you can totaly start your prefered terminal emulator with ranger and you have a functional file browser, or with amixer/pulsemixer and you have your volume control "gui"...
it's like "every app is a web page" but terminal version
@bartavi @b0rk While I can't speak for Julia's perspective, mine is that the shell's primary interface with programs you run is _process control_ - creating process groups, forking new processes into them, executing programs in those forks, awaiting termination, and in some cases sending shell-originated signals to carry out job management.
@b0rk I had never considered "shell" as a safe little place to hide a delicious body in.
@b0rk This may be an efficiency trade-off from way-back, when it would have been expensive to intercept terminal output? Maybe that's also why we talk "raw" to terminals at all... the standard could have been a TUI. And IBM mainframes do things very differently, also for efficiency.
@b0rk Yeah, that's definitely been my model for ages. I'm going to have to go learn how this interaction actually plays out.
@b0rk I think this is a useful simplification for basic understanding of how most people work in a terminal. The shell is an agent that we use to work with the operating system. You could put another box around the shell and programs for the operating system.
@EricFielding haha the problem is that it's really not true at all, like programs' interactions with the operating system do not go through the shell in any way
@b0rk @EricFielding on a micro-kernel unixlike many years ago I had to debug and fix an issue with ^C killing the serial driver.
That was quite a lesson in what's going on with terminal drivers and everything around them
In that space the shell is Just Another Program
@RandomDamage @b0rk @EricFielding
I think in unix-like OS in general the shell is just another program. Maybe people feel like the shell is in between the terminal and the program because the program is run from the shell and people feel like it's running "inside" the shell somehow.
I guess the name "shell" gives that impression of containment too. It's probably too late to start calling it something else :)
@petealexharris @RandomDamage @b0rk @EricFielding The "shell" name comes from the metaphor of a (nut) kernel and shell, with the shell wrapping the kernel not the other program. Still, that metaphor also wrongly implies that other programs don't communicate directly with the kernel
@b0rk @EricFielding _are_ there things that some shells do while a program is running?
Stuff like tty output is probably dangerous territory, because the spawned program may have changed terminal modes, etc.
Timers might be useful (i.e. kill this program after 30s). There's also all the job control stuff that runs $sometime... Still, I think the mental model of `fork+exec` and `fork+wait` is probably a good first approximation.
@EricFielding @b0rk although now I'm actually curious about the terminal driver/stty and control-c/SIGINT handling.
Know I've figured this stuff out at some point, and forgotten it, but may have to keep searching.
@danlyke @EricFielding @b0rk The shell is pretty deeply involved in *job control* but that basically just involves telling the kernel "hey, this process group is in the foreground now" and then it gets out of the way and lets the foreground job and the kernel work it out on their own. And this is a lot less obvious now that most people don't actually use job control.
@b0rk The results of the first two polls on this topic were way more even than I expected. Clearly you’ve found a topic people are unsure of.
And after seeing those results, my confidence level in my mental model is a lot lower too.
@b0rk This conundrum has "waterfall model" vibes to it. Everyone who teaches it knows (or should know) that waterfall is wrong, but the teaching material insists on presenting it first like it's some kind of archetype that every other model is based on.
On the other hand, we also know that Newtonian physics stop working at very large or very small scales, but we teach it anyway because it's a good enough approximation in the general case.
@b0rk I feel like teaching multiple mental models is entirely valid.
In systems thinking, people use multiple "lenses" on the same problem to gather different kinds of insights. Teaching multiple models will yield different insights for different audiences.
Of course, the easier/smoother you can lead people from the wrong-but-simple/useful model to the correct-but-complex model, the better :)
@zekjur @b0rk reminds me of how I learned about the composition of atoms in chemistry/physics at school. It starts with a simple/relatable mental model and then every year or two it's "surprise! we lied (again!), it's really like this!" until you get to quantum probability stuff. I have mixed feelings about how that was presented: none of my teachers said "here's a simple model, it's a bit more complicated in reality" before saying "this is how it is", but it did make it easier to learn.
@b0rk This is reminding me that one of my college computer science courses included an assignment to implement features of a basic shell, but that's been a really long time now
@mulad something I've been learning from these replies is that the “implement a shell" project actually in a way causes more confusion because you can implement a shell in a lot of different ways and not all of those are actually the same as how the shells we use work
(which is fine, like it's cool to do things in different ways, but for me implementing a toy shell definitely gave me some slightly wrong ideas about how shells work)
@b0rk for me terminal has also ssh and tmux, so complicating everything. Also the desktop manager will intercept some keys. A spaghetti flow. I wonder if someone really understands all details (compressing x kbd settings, DM/DE, serial protocol (still not completely hidden), terminal (strange settings), vim and emacs (pushing things at extreme), tmux, …
@cate yeah ssh and tmux make everything SO much more confusing
@b0rk@social.jvns.ca I mean... Is it wrong? Shell launches these programs and forwards i/o, so in a way, this is the only technically accurate visualisation (because the process tree actually does look like this)
@addison it is wrong, the shell does not forward i/o, when it forks the process just inherits the same file descriptors and talks to the OS directly :)
(but it doesn't necessarily "matter" to be wrong in that way, like you can get along fine if you think the shell forwards I/o)
@b0rk@social.jvns.ca wait oh no
It doesn't just pass the stdin/stdout on fork/execve? I know there's some wonkiness when you're working with ttys but I wasn't really thinking about this
@addison i mean it does kind of make a copy of its stdin/stdout on fork (in the sense that that happens automatically when you fork a process) but like it's not actively involved in forwarding anything beyond just running `fork` and `execve` one time when starting the process
@b0rk@social.jvns.ca Hm. I guess I always think of that as forwarding, but I see how this is a model that doesn't reflect reality... Wonky. I guarantee that this model has weird inconsistencies with reality with seekable fds or debugging multithreading, but for shells, I think this model at least captures the "vibe" of how shells interact with waiting programs (unless they're backgrounded... oh well)
@b0rk I found this a very permissive idea: @gvwilson ‘s Rule 6 about teaching tech: “Never hesitate to sacrifice truth for clarity.”
https://teachtogether.tech/en/
I take this to mean that it’s ok to start with something “wrong” that makes sense, if it helps to get the learner closer to the “right” than before.
Disclaimers never hurt too, I guess…
The real issue with "true" vs "clear" is that the shell owns the process the terminal is talking to, but isn't a 100% middleman.
I'd run with clarity over truth, with a footnote that reality is more complex. Ie. Just what you're doing. There is nothing wrong with a mental model that simplifies learning, so long as we all understand there's ugly details under the hood somewhere.
@b0rk I struggle with something similar as well when doing user training or collaborating with others who have different areas of expertise.
At some point I end up saying “because” or “magic” because we are past the point where more details are helpful. And I never know if that is the best approach.
@b0rk "All models are wrong, but some models are useful"
Sometimes it's useful to think about a system in a simplified way that you know is wrong, provided you remain aware of that?
@b0rk It was so much easier when terminals were real terminals, connected to serial lines. The model was simpler to grasp because there were fewer pieces.
@b0rk just like preschool, I want teachers that tell me the truth. I realize the map is never the terrain, so any lesson contains falsehoods, but I think there is always value in being as close to reality as possible.
This isn't advice. It's just what I want as a paying customer. :)
@heathborders yea telling the truth is the only option, I just need to figure out how to do it
@b0rk I appreciate all your content. Thank you for the great work you're doing. Just one feedback If I may: repeating "not looking for advice" or "not looking for answers" in almost every post is sometimes annoying to the reader (sorry I can' find another word to describe it). Can you explain why do you feel the need to repeat this every time?
@imjam mastodon used to be almost unusable for me because I would get a lot of super repetitive replies to all my posts. Adding the disclaimers makes it possible for me to continue using mastodon, the alternative is probably that I would leave
@b0rk this means this disclaimer helped you, fair enough. Happy you stayed, just ignore my feedback then! Have a great day.
@b0rk I do think that explaining the nitty gritty details of the real model has a quite niche audience, to the point where it may not be worthwhile going there depending on what your goal is, but I think there is a level of truthful simplification that has a much broader audience while not just making up a whole different model of how things fit together like in the example in that previous picture.