英文:
enter SIGTSTP signal in child process, different child process behaves differently?
问题
I'm implement my own shell on MAC, in my own shell, when I enter "Control+Z" or "Control+C", it should ignores them. but when running the command such as "sleep 10" or "cat". It behaves as default.
However, in my implementation, it behaves weird.
void sig_handler(int signo) {
if (signo == SIGINT || signo == SIGQUIT || signo == SIGTSTP) {
// ignores
} else {
// other signals, behaves default
signal(signo, SIG_DFL);
raise(signo);
}
}
int main() {
signal(SIGINT, sig_handler);
signal(SIGTSTP, sig_handler);
signal(SIGQUIT, sig_handler);
while (1){
printf(">> ");
fflush(stdout);
//parse the input; skip the code for simplicity
cmd = parse_input();
// for example, cmd = {"cat", NULL}; or cmd = {"sleep", "60", NULL}, or cmd = {"ls", NULL}
pid_t child_pid;
pid = fork();
if (pid < 0) {
perror("error: fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
child_pid = pid;
execvp(cmds[0][0], cmds[0]);
perror("error: exec");
exit(EXIT_FAILURE);
} else {
int status;
waitpid(child_pid, &status, WUNTRACED | WCONTINUED);
}
}
}
when I run the program with the following user input, it displays as follows
>> cat
^Z>> ls
>>
I first enter cat
, then enter Control+Z
, the terminal goes back to waiting for user input. But when I enter ls
next, it's supposed to list all files in the current directory, but it just shows a newline, and when I hit "return" again, it goes back to waiting for user input. Only then, it seems back to a normal shell prompt.
>> sleep 10
^Z>> ls
file1 file2 file3
>>
Instead of cat, we use sleep
, and the program seems to handle "Control+Z" as expected.
Any help
英文:
I'm implement my own shell on MAC, in my own shell, when I enter "Control+Z" or "Control+C", it should ignores them. but when running the command such as "sleep 10" or "cat". It behaves as default.
However, in my implementation, it behaves weird.
void sig_handler(int signo) {
if (signo == SIGINT || signo == SIGQUIT || signo == SIGTSTP) {
// ignores
} else {
// other signals, behaves default
signal(signo, SIG_DFL);
raise(signo);
}
}
int main() {
signal(SIGINT, sig_handler);
signal(SIGTSTP, sig_handler);
signal(SIGQUIT, sig_handler);
while (1){
printf(">> ");
fflush(stdout);
//parse the input; skip the code for simplicity
cmd = parse_input();
// for example, cmd = {"cat", NULL}; or cmd = {"sleep", "60", NULL}, or cmd = {"ls", NULL}
pid_t child_pid;
pid = fork();
if (pid < 0) {
perror("error:fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
child_pid = pid;
execvp(cmds[0][0], cmds[0]);
perror("error:exe");
exit(EXIT_FAILURE);
} else {
int status;
waitpid(child_pid, &status, WUNTRACED | WCONTINUED);
}
}
}
when I run the program with the following user input, it displays as follows
>> cat
^Z>> ls
>>
I first enter cat
, then enter control+Z
, the terminal goes back to waiting for use enter prompt. But when enter ls
next, it supposed to list all files in current directory, but it just shows a newline, and when I hit "return again, it goes back to waiting for user to enter prompt. Only then, it seems back to normal shell prompt.
>> sleep 10
^Z>> ls
file1 file2 fil3
>>
instead of cat, we use sleep
, the program seems handle "control+Z" as expected .
Any help
答案1
得分: 1
From the documentation of signals:
> During an execve(2), the dispositions of
handled signals are reset to the default; the dispositions of
ignored signals are left unchanged.
Since you're handling these signals with the sig_handler()
function, they get reset to the default disposition when you do execvp(cmds[0][0], cmds[0]);
. (How could it make sense not to reset them, since the function doesn't exist in the cat
and ls
programs?)
So you should ignore them, not handle them:
signal(SIGTSTP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
英文:
From the documentation of signals:
> During an execve(2), the dispositions of
handled signals are reset to the default; the dispositions of
ignored signals are left unchanged.
Since you're handling these signals with the sig_handler()
function, they get reset to the default disposition when you do execvp(cmds[0][0], cmds[0]);
. (How could it make sense not to reset them, since the function doesn't exist in the cat
and ls
programs?)
So you should ignore them, not handle them:
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论