I'm using sigaction(SIGTSTP, &ctrlz_signal, NULL);
to ensure I can catch Ctrl-Z
.
void ctrlz_signal(int sigNo) {
printf("Caught Ctrl-Z | curr_chld=%d\n", CURR_CHILD);
if(CURR_CHILD != 0) kill(CURR_CHILD, SIGTSTP);
}
CURR_CHILD
is set through forking:
sigaction(SIGTSTP, &ctrlz_signal, NULL);
int status;
CURR_CHILD = fork();
if (CURR_CHILD < 0) {
// ...
} else if (CURR_CHILD == 0) { // child
// exec(...)
} else { // back in parent
waitpid(CURR_CHILD, &status, 0); // wait for child to finish
// ...
}
It seems like it successfully stops the child process, but then it doesn't trigger the parent's waitpid
. I would've thought there would be a signal sent to the parent when I'd use this kill
function, but it seems like it isn't since my "shell" gets stuck on that waitpid
line.
How do I make it so that, once Ctrl-Z
is pressed, the process running an exec
command (which is a child, at that point) should be put in the background (stopped), and then the parent process should gain back its control over the flow of the program ?
printf
is not an async-signal-safe function (as it is not re-entrant) and therefore must not be used in a signal handler. Using such functions will lead to undefined behavior.
If you want a child process that is not traced with ptrace
to return, you have to specify the WUNTRACED
option when you use waitpid
.
Alternatively, you can use ptrace
with the PTRACE_TRACEME
option, so that it will provide status for the child process even if the WUNTRACED
option is not specified in the waitpid
call.