[英]Why do my program behave unexpectedly when I use sigaction?
I'm writing my own simple shell as an exercise.我正在编写自己的简单 shell 作为练习。 I need to register to the
SIGCHLD
signal in order to handle zombie-processes.我需要注册到
SIGCHLD
信号才能处理僵尸进程。 For some reason, when I add the handler using sigaction
the program exits, and I don't understand why.出于某种原因,当我使用
sigaction
添加处理程序时,程序退出,我不明白为什么。
You can see in main()
that we exit if process_arglist()
returned 0
but I return 1
and I don't see how the signal handling could affect that.您可以在
main()
中看到,如果process_arglist()
返回0
,我们将退出,但我返回1
,我看不到信号处理会如何影响它。
Here's my code.这是我的代码。 It should handle a command ending with an
&
(we fork()
and use execvp
in the child code).它应该处理以
&
结尾的命令(我们fork()
并在子代码中使用execvp
)。 For example: ping 127.0.0.1 -c 5 &
.例如:
ping 127.0.0.1 -c 5 &
。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
void sigchld_handler(int signal) {
int my_errno = errno;
while (waitpid(-1, 0, WNOHANG) > 0); // WNOHANG so handler will be non-blocking.
errno = my_errno;
}
int handle_background_command(int count, char** arglist) {
pid_t pid;
arglist[count - 1] = NULL; // remove "&" from arglist
//Handle SIGCHLD signal
struct sigaction sa, sa_dft;
sa.sa_handler = sigchld_handler;
sa.sa_flags = SA_NOCLDSTOP;
if (sigaction(SIGCHLD, &sa, &sa_dft) == -1) {
perror("error when trying to set signal action");
exit(-1);
}
if((pid = fork()) == -1) {
perror("error when trying to fork() from handle_background_command()");
exit(1);
}
if(pid == 0) {
// Child code
sigaction(SIGCHLD, &sa_dft, NULL);
if(execvp(arglist[0], arglist) == -1) {
perror("error when trying to execvp() from handle_background_command()");
exit(1);
}
}
// Parent code
return 1;
}
int process_arglist(int count, char** arglist)
{
return handle_background_command(count, arglist);
}
int main(void)
{
while (1)
{
char** arglist = NULL;
char* line = NULL;
size_t size;
int count = 0;
if (getline(&line, &size, stdin) == -1) {
printf("out!");
break;
}
arglist = (char**) malloc(sizeof(char*));
if (arglist == NULL) {
printf("malloc failed: %s\n", strerror(errno));
exit(-1);
}
arglist[0] = strtok(line, " \t\n");
while (arglist[count] != NULL) {
++count;
arglist = (char**) realloc(arglist, sizeof(char*) * (count + 1));
if (arglist == NULL) {
printf("realloc failed: %s\n", strerror(errno));
exit(-1);
}
arglist[count] = strtok(NULL, " \t\n");
}
if (count != 0) {
int result = process_arglist(count, arglist);
printf("result = %d\n", result);
if (!result) {
free(line);
free(arglist);
printf("out\n");
break;
}
}
free(line);
free(arglist);
}
pthread_exit(NULL);
return 0;
}
Again, if I get rid of the signal handling code then it works.同样,如果我摆脱了信号处理代码,那么它就可以工作了。
What's the reason?什么原因?
EDIT Here's the output (last rows) of strace
utility:编辑这是
strace
实用程序的输出(最后一行):
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2818, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, NULL, WNOHANG, NULL) = 2818
wait4(-1, NULL, WNOHANG, NULL) = -1 ECHILD (No child processes)
rt_sigreturn() = -1 EINTR (Interrupted system call)
write(1, "out!", 4out!) = 4
exit_group(0) = ?
+++ exited with 0 +++
Your program exits with EINTR (interrupted system call) from getline function (getline is interrupted by signal handler).您的程序从 getline 函数(getline 被信号处理程序中断)以 EINTR(中断的系统调用)退出。
Check this: How to handle EINTR (interrupted System Call)检查这个: 如何处理 EINTR(中断的系统调用)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.