SIGCHLD导致分段错误,而不是进入处理程序

我正在尝试创建一个简单的shell,并添加了使用&在后台运行进程的function。 在我的主要方法中,我基本上有:

int main() { if (signal(SIGCHLD, handle) == SIG_ERR) perror("Cannot catch SIGCHLD"); pid_t child = fork(); if (child == 0) execvp(command, arguments); else { if (background == 1) { printf("1"); backgroundList(command, child); printf("2"); } else waitpid(child, NULL, 0); } } 

对于我的经纪人,我有:

 void handle(int s) { printf("a"); if (signal(SIGCHLD, handle) == SIG_ERR) perror("Cannot catch SIGCHLD"); pid_t pid; printf("b"); while((pid = waitpid(0, NULL, WNOHANG)) > 0) { printf("c"); rmBackgroundList(pid); printf("d"); } } 

我可以让它在前台运行一个进程就好了。 运行“ls”将内容打印到屏幕上,然后打印“a”和“b”,因为它进入SIGCHLD处理程序,但它不会转到“c”,因为它已经等待了。

但是,在后台运行一些东西(“ls&”)将打印“1”和“2”,让父母返回提示,然后孩子将内容打印到屏幕,然后分段错误。 它不会打印处理程序中的任何字母。

我无法弄清楚为什么SIGCHLD对已经等待但却导致分段错误的孩子有好处,甚至从未进入处理器以处理未等待的进程。

您没有遵循信号处理程序的规则。 你不能使用printf()perror() 。 阅读有关信号处理程序中可安全操作的规则。

signal()的行为也会发生变化,这取决于它是否是BSD或SysV样式的Unix。 Linux基于_BSD_SOURCE或_GNU_SOURCE的存在改变其在glibc中的行为,并且根据您是否调用gcc -ansigcc -std=c99gcc -std=gnu99

你应该使用sigaction()而不是signal()