-
Notifications
You must be signed in to change notification settings - Fork 503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Signal handling omni issue #2473
Comments
Here's my tentative plan so far. The interesting signals are When not running a child process, When a child process is running:
In all of the above cases, just should record that a fatal signal was received, and when the child returns, even if it returns successfully, Obviously, all this should be documented thoroughly. Where does this go wrong?
How is this different from current behavior?
PS For fun, I think we should also print out something useful if |
I think that's the problem really, |
@OJFord Using this foo:
#!/usr/bin/env bash
function sigusr1() {
echo sigusr
}
function siginfo() {
echo siginfo
}
trap sigusr1 SIGUSR1
trap siginfo SIGINFO
while true; do
sleep 1
done I was able to invoke the handler functions with |
I've just stumbled upon this issue while trying to figure out how just handles signals. specifically i have a justfile like this:
so my intention here is to always delete the tmp-dir after the build is done. i tried but no dice. tbh I'm not fully sure what I'm asking here, either:
based on the above comment, the following does work tho:
I don't know if this is the right issue to write this in, if not please tell me :) |
This is definitely the right issue!
|
even tho that might solve my "usecase" tbh i don't know if that would be obvious/non-surprising behavior |
I think it can be argued both ways. It is maybe a little surprising that an infallible line isn't infallible if it's terminated by a signal. |
true. i guess the question is really what the user thinks they are "stopping" when hitting ctrl+c: the current "step" or the whole recipe. the approach that you described above regarding SIGINT seems reasonable for this tho. it might also be worth thinking about something like this: |
There are a bunch of issues related to how
just
handles signals. I've been trying to figure out what they are, so I created this issue to collect all the information in one place, and summarize what's going on.Way back in 2018, in #302, @bheisler opened an issue that
just
was not waiting for child processes to exit on CTRL-C (which sendsSIGINT
). This would cause them to be orphaned, and continue writing output to the terminal, and have to be cleaned up manually.In response to #302, I merged #345, which made just ignore
SIGINT
,SIGHUP
, andSIGTERM
while running commands.SIGINT
is CTRL-C,SIGHUP
is sent when you close the terminal ("hup" is for "hangup"), andSIGTERM
is the signal which thekill
command sends by default.This gave
just
the behavior it has now. When running a long-running command, for examplesleep 60
, if you hitCTRL-C
,just
will ignore the generatedSIGINT
signal, but, depending on your terminal or setup, hittingCTRL-C
sendsSIGINT
to all processes in the foreground process group, sosleep 60
will receiveSIGINT
which will terminate it,just
will see it was terminated with a signal, andjust
will return with an error reporting that it terminated with a signal.There appear to be a number of issues with this behavior, reported in:
Running Firestore Emulator From Just Prevents Control C #1558 by @LLBlumire. Here,
just
is used to rungcloud emulators firestore start
. Whengcloud emulators firestore start
is run on its own,CTRL-C
stops it, but when run underjust
,CTRL-C
does nothing.I'm not entirely sure what's going on here. When you do
sleep 60
underjust
,CTRL-C
gets sent tojust
, which ignores it, but also gets sent tosleep 60
, which terminates it.What's going on in this case? Why isn't
CTRL-C
getting sent to thegcloud
command? WhenCTRL-C
is hit, it is the system (some combination of the kernel, shell, terminal) which arranges to sendSIGINT
to the relevant processes, so I'm not sure whatjust
could be doing to interfere with this.Trap signals? #1560 by @OJFord. I'm not sure what's going on here, because the signals mentioned are
SIGUSR1
, andSIGINFO
(generated byCTRL-T
), which I don't thinkjust
touches at all. However, @stefanchrobot mentions that his app terminates when it receivesSIGTERM
, but nothing happens if the same command is run underjust
.SIGHUP seems to not be propagated to inner child processes #1781 by @davoclavo. Here,
just
is not responding toSIGHUP
. This is expected, becausejust
ignores these signals while running child processes. This isn't necessarily bad, because in the normal case,SIGHUP
is sent to all members of the process group, which should terminate the child and cause it to exit.Improve signal/interrupt handling #1803 PR by @davoclavo. Reworks the signal handler to actively poll for new signals, and terminate the child when it receives one. Never got merged, I think due it being hard to implement/test on Windows.
I'll also summarize what I know about signals, which may be wildly off.
The relevant signals are:
SIGHUP
Sent when the terminal is closed.SIGINT
Sent on CTRL-C.SIGTERM
Sent by default by thekill
command.Currently,
just
runningsleep 60
, will close when you hit CTRL-C or close the terminal. This is, I believe, because CTRL-C and closing the terminal not only send the signal to the foreground process, but also to members of the foreground process group. So just ignores theSIGHUP
orSIGINT
signal, butsleep
receives it and terminates, sojust
, which is waiting for it, sees that it has stopped and terminates it as well.If you generate
SIGHUP
,SIGINT
, orSIGTERM
manually, withkill -s HUP/INT/TERM
and send it tojust
, nothing will happen, because onlyjust
is receiving the signal, not the childsleep
process.I think the fact that in some cases, a signal is sent to a single process, and in some cases, all members of a process group, causes confusion, since it means that a
SIGINT
generated by a CTRL-C will have a different effect from one generated by thekill
command, even though it's the same signal.As far as I know, a parent process is not responsible for "forwarding" signals to child processes, it's the terminal / system which does this, so I don't think
just
is interfering with that. (The only possible exception to this is the process signal mask, which indicates some signals that should be ignored, and which is inherited by child processes. However,just
does not set the signal mask, so this should not be an issue.)Also, I don't know how this varies between different setups, because there are a lot of variables.
just
at all on Windows?just &
?tmux
,zellij
,dtach
, etc?Here are my current questions:
When is ignoring
SIGINT
andSIGHUP
,just
's current behavior, desirable? IfSIGINT
andSIGHUP
are sent withCTRL-C
or closing the terminal, they should be sent to all children, and thus everything should get cleaned up. I think it would only be in the case of child processes which don't handle these signals that anything doesn't get cleaned up, so a reasonable argument might be thatjust
shouldn't try to handle this, and it's the fault of the child processes that they aren't responding to these signals.When is ignoring
SIGTERM
,just
's current behavior, desirable? This is a bit different fromSIGINT
andSIGHUP
, sinceSIGTERM
, when sent withkill $JUST_PID
, is not sent to child processes, so ifjust
exited, it would leave behind child processes.How can I reproduce examples of
just
processes not terminating when they should? An example from SIGHUP seems to not be propagated to inner child processes #1781 is withzellij
, but I wasn't able to reproduce this. If I create azellij
session, open two tabs, runjust
with a recipe that callsjust sleep
, and then close the tab,just sleep
is not left running in the background.just
ignoresSIGINT
andSIGHUP
. As far as I can tell, this is fine, sinceSIGINT
andSIGHUP
should be sent to child processes onCTRL-C
and terminal close, sojust
can just ignore them and wait for children to exit. Are there cases when this is problematic?just
ignoresSIGTERM
, which is sent bykill
. As far as I know, this signal only gets sent tojust
, so it may be surprising that it doesn't stopjust
. Should we changejust
to forwardSIGTERM
to child processes, so thatkill $JUST_PID
will causejust
to exit? (Assuming that child processes respond toSIGTERM
by exiting.)My current thoughts are:
I think that
just
should probably not ignoreSIGINT
andSIGHUP
. These signals are generated byCTRL-C
and closing the terminal, respectively, and should be sent to children ofjust
as well. So, unless something is wrong,just
and all children should exit, which is what the user wants.I think that
just
should probably either ignoreSIGTERM
, or forward it to any running child processes. If the user runskill $JUST_PID
, this only sendsSIGTERM
tojust
, so if it exits, it will leave child processes behind.I think the original reason for ignoring
SIGINT
was not necessarily a good one. In that particular use-case,just
was being used to run a test runner which would interpretCTRL-C
as a failed test, but continue with further tests. So ifjust
ignoredCTRL-C
, you could hold it down and it would eventually run out of tests to run and exit. However, most programs exit immediately onCTRL-C
, so I don't think it makes sense to optimize for the case thatCTRL-C
doesn't terminate child processes.(Sorry for tagging a bunch of people! I wanted to make sure people were aware of the new issue. Feel free to unsubscribe!)
The text was updated successfully, but these errors were encountered: