You are not logged in.
Hello,
I'm currently learning bash, and I'm doing a script in which i want to trap SIGINT during the execution of the script.
I used:
trap '' SIGINT
This effectively prevents the interruption of the script if the user presses "CTRL+C"
The problem arises when i run a line with pacman.
In that case if the user presses "CTRL+C" SIGINT still gets sent and pacman stops running.
Can someone explain me why this is the behaviour and if there are ways to actually to what i want?
Thanks!
Last edited by RandomShinyDog (2024-04-24 16:09:56)
Offline
Your script isn't running, pacman is, the interrupt goes to pacman, afterwards your script runs again.
Generally this has all the markings of an XY question when asking things, please post the full scope of your question in this case, your full current script, what you want to do, what your actual end goal is, why you think you want to do it that way and where exactly you are stuck.
Last edited by V1del (2024-04-23 16:35:43)
Offline
Ok sorry, I thought the problem was pretty much self explanatory. I will try to be more specific.
Let's say I have the following bash script:
#!/bin/bash
trap "" SIGINT
sleep 5
for x in {1..5}; do
echo hello!
sleep 2
done
echo "Starting tree..."
sleep 2
tree /
echo "Starting pacman..."
sleep 2
pacman -S linux
echo "End of script, bye!"
If i press Ctrl+C during the execution SIGINT gets ignored and the script keeps going on. This works for every command but not for pacman.
As you pointed out the problem is that the interrupt is going to pacman and not the script.
How can I make it ignore SIGINT even when pacman is executing?
Again, there is no real point to this, I'm just trying to learn bash and I would like to better understand the part regarding signals.
One solution I was thinking was is to disable stdin for the terminal completely when the script is running, but I'm not sure how dirty of a workaround this would be, and I don't even know to implement this.
Last edited by RandomShinyDog (2024-04-24 13:54:06)
Offline
Yes, we got what you were trying to do, but not *why* you would want to do this. It's a bad idea in general.
Offline
Yes, we got what you were trying to do, but not *why* you would want to do this. It's a bad idea in general.
Sorry, I was editing my answer when you just responded.
No *real* reason to do this, I'm just trying to learn bash and I would like to understand possible workarounds, if any are possible.
Offline
One solution I was thinking was is to disable stdin for the terminal completely when the script is running, but I'm not sure how dirty of a workaround this would be, and I don't even know to implement this.
Closing the stdin is neither a hack nor overly complicated, but how are you then going to interact w/ pacman?
You could adapt https://github.com/coreutils/coreutils/ … rc/nohup.c to some "noint.c", but that really doesn't have to do anything with "learning bash" and also isn't a good idea.
Lastly, and I assume that this is where this entire thing is headed, you could re-bind ctrl+c in your terminal emulator to not generate a sigint (but copypasta, I guess)
Online
One solution I was thinking was is to disable stdin for the terminal completely when the script is running, but I'm not sure how dirty of a workaround this would be, and I don't even know to implement this.
Closing the stdin is neither a hack nor overly complicated, but how are you then going to interact w/ pacman?
You could adapt https://github.com/coreutils/coreutils/ … rc/nohup.c to some "noint.c", but that really doesn't have to do anything with "learning bash" and also isn't a good idea.
Lastly, and I assume that this is where this entire thing is headed, you could re-bind ctrl+c in your terminal emulator to not generate a sigint (but copypasta, I guess)
With stdin closed I could, for example, run "pacman --noconfirm" and just wait until it exits.
I tried with
exec 0<&-
but it doesn't seem to block stdin.
Re-binding ctrl+c could be a solution but I would like a solution which is portable and not terminal based.
Offline
Solution to what? I thought you're just trying to learn bash?
Online
Solution to what? I thought you're just trying to learn bash?
Solution to:
How can I make it ignore SIGINT even when pacman is executing?
Offline
That's not looking for a solution but an answer and regardless or linguistic nitpicks:
I would like a solution which is portable and not terminal based
Why would there be any preference?
Why does it need to be "portable"?
Why can it then be limited in scope to the very narrow "user doesn't have to do input at all"?
Why would you want to intercept sigints itfp?
Generally this has all the markings of an XY question when asking things, please post the full scope of your question … what you want to do, what your actual end goal is, why you think you want to do it that way and where exactly you are stuck.
There's a reason why nohup exists, there is no other sane way to intercept HUPs - same goes for INT, except nobody ever thought it might be a good idea to intercept those.
Closing the stdin of the shell won't work.
Closing the stdin of the (pacman) process won't work.
The relevant stdin is the one of the terminal.
Online
Your stated goal is to understand BASH and there is headway to be made there, but not in a direct solution to your question as stated, but rather in understanding why your question is completely nonsensical in the first place. Upon interpreting line 17 of your script "pacman -S linux" BASH calls fork() after which there are two BASH processes running in parallel, one in the foreground which could be interrupted via SIGINT from the controlling terminal, and the other in the background which would not receive this signal (at least not via the default mechanisms invoked by pressing Ctrl-C).
Immediately after this, the foreground BASH process then calls an 'exec' family function, most likely execv() passing arguments like "pacman", "-S", "linux" to that exec function. This results in the pacman process replacing the foreground BASH process. That foreground BASH process is no more, it has ceased to be, it has expired and gone to meet it's maker, it is a late shell; it's a stiff, bereft of life, it rests in peace ... it is an ex-shell. It has been replaced by pacman. So there is no foreground shell to receive (and potentially handle) the SIGINT from the controlling terminal. Any SIGINT sent at this time goes directly to pacman.
Only after pacman has completed does control return to that other background BASH process (which now becomes foreground).
That is a bit of understanding of BASH. Everything that happens while pacman is foregrounded is not about understanding BASH.
So either you want to understand BASH and what happens when pacman is running is not relevant, or you have a different question that would apply just as much when pacman is running. In the case of the former, are we done here? In the case of the latter, please define what that actual question is as has already been requested, as such a question is most definitely not about understanding BASH.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
That's not looking for a solution but an answer and regardless or linguistic nitpicks:
I would like a solution which is portable and not terminal based
Why would there be any preference?
Why does it need to be "portable"?
Why can it then be limited in scope to the very narrow "user doesn't have to do input at all"?
Why would you want to intercept sigints itfp?
There isn't really any actual use for this, in my head I was just wondering: "what would happen if a script is doing something very critical and I wouldn't want the user to press ctrl+c (maybe even by mistake) in order to avoid any possible trouble?".
Hence the reason for asking how it would be possible to intercept sigint.
Maybe you find it weird that I'm doing something for no real reason, but it is just a doubt that I got while coding and wanted to find an answer to the problem.
There's a reason why nohup exists, there is no other sane way to intercept HUPs - same goes for INT, except nobody ever thought it might be a good idea to intercept those.
Closing the stdin of the shell won't work.
Closing the stdin of the (pacman) process won't work.
The relevant stdin is the one of the terminal.
Ok, then how could I close stdin of the terminal?
Offline
... I wouldn't want the user to press ctrl+c (maybe even by mistake) in order to avoid any possible trouble?
If you want to prevent this, then just don't leave that critical process running in the foreground.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Your stated goal is to understand BASH and there is headway to be made there, but not in a direct solution to your question as stated, but rather in understanding why your question is completely nonsensical in the first place. Upon interpreting line 17 of your script "pacman -S linux" BASH calls fork() after which there are two BASH processes running in parallel, one in the foreground which could be interrupted via SIGINT from the controlling terminal, and the other in the background which would not receive this signal (at least not via the default mechanisms invoked by pressing Ctrl-C).
Immediately after this, the foreground BASH process then calls an 'exec' family function, most likely execv() passing arguments like "pacman", "-S", "linux" to that exec function. This results in the pacman process replacing the foreground BASH process. That foreground BASH process is no more, it has ceased to be, it has expired and gone to meet it's maker, it is a late shell; it's a stiff, bereft of life, it rests in peace ... it is an ex-shell. It has been replaced by pacman. So there is no foreground shell to receive (and potentially handle) the SIGINT from the controlling terminal. Any SIGINT sent at this time goes directly to pacman.
Only after pacman has completed does control return to that other background BASH process (which now becomes foreground).
That is a bit of understanding of BASH. Everything that happens while pacman is foregrounded is not about understanding BASH.
So either you want to understand BASH and what happens when pacman is running is not relevant, or you have a different question that would apply just as much when pacman is running. In the case of the former, are we done here? In the case of the latter, please define what that actual question is as has already been requested, as such a question is most definitely not about understanding BASH.
Thanks for making it clear, now it makes more sense to me.
I guess the case is a bit of a mix of both.
Regarding former point, it wasn't clear to me what was going on, and that's why I first asked for this, as for commands like tree trap seemed to work, but not for others like pacman.
Regarding latter point, the reason for this is explained in my last reply.
How do you handle a user inputting a ctrl+c while a critical process is currently going on? Ignoring SIGINT seemed like a reasonable solution to me.
Offline
RandomShinyDog wrote:... I wouldn't want the user to press ctrl+c (maybe even by mistake) in order to avoid any possible trouble?
If you want to prevent this, then just don't leave that critical process running in the foreground.
Oh, for some reason I didn't think of this.
Even though that would prevent any text to be printed to foreground
Last edited by RandomShinyDog (2024-04-24 15:49:53)
Offline
I just hacked around for a while with job control and managed to do this:
#!/bin/bash
trap "" SIGINT
set -m
pacman -Syu &
bg %+
wait -f %1
The pacman instance is immune to ^Cs, and also seemingly all input from the terminal, but its stdout is still visible. It looks like Trilby had the same idea.
"Don't comment bad code - rewrite it." - The Elements of Programming Style (1978), Brian W. Kernighan & P. J. Plauger, p. 144.
Offline
Even though that would prevent any text to be printed to foreground
Backgrounding a process does not prevent it from sending text to stdout ... at all.
But if you just background it (e.g., with an ampersand at the end) then the output will be interwoven with the next prompt or other output from the foreground process. 256 shared one way of preventing this.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
I just hacked around for a while with job control and managed to do this:
#!/bin/bash trap "" SIGINT set -m pacman -Syu & bg %+ wait -f %1
The pacman instance is immune to ^Cs, and also seemingly all input from the terminal, but its stdout is still visible. It looks like Trilby had the same idea.
Thanks, this is exactly what I was looking for
Offline