后台进程的信号处理
Signal handling for background processes
我试图在 C 中实现一个简单的 Unix shell。但是,我无法使用 sigaction 实现后台进程功能。我的代码结构如下:
int main() {
struct sigaction act;
act.sa_handler = handler;
sigaction(SIGCHLD, &act, 0);
while(1) {
parseCommand();
execCommand();
}
}
此外,在我的 execCommand 函数中,结构如下:
if (fork()) {
if (!isBackground) {
wait(&child_status);
}
else
printf("Background process\n");
}
else
... // Command execution...
我的处理程序如下所示:
void handler(int s) {
while (waitpid(-1, NULL, WNOHANG) > 0) {
}
printf("OK.\n");
}
但这种结构损害了我的整个实施。即使是前台进程也无法正常工作。当我执行前台命令时,它给出:
Segmentation fault (core dumped)
当我执行后台命令时,它给出:
Bus error (core dumped)
那么,我该如何解决这个问题呢?
提前致谢...
编辑:当我用 valgrind 调试我的代码时,它给出以下内容:
==6768== Memcheck, a memory error detector
==6768== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6768== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==6768== Command: ./shell
==6768==
==6768== Syscall param rt_sigaction(act->sa_mask) points to uninitialised byte(s)
==6768== at 0x4E6F5AE: __libc_sigaction (sigaction.c:62)
==6768== by 0x400E90: main (in /home/enes/Desktop/Shell/shell)
==6768== Address 0xffefff908 is on thread 1's stack
==6768==
==6768== Syscall param rt_sigaction(act->sa_flags) points to uninitialised byte(s)
==6768== at 0x4E6F5AE: __libc_sigaction (sigaction.c:62)
==6768== by 0x400E90: main (in /home/enes/Desktop/Shell/shell)
==6768== Address 0xffefff8f8 is on thread 1's stack
==6768==
> ls
==6768== Use of uninitialised value of size 8
==6768== at 0x4EA8C80: _IO_getline_info (iogetline.c:77)
==6768== by 0x4EA7B7C: fgets (iofgets.c:53)
==6768== by 0x400EC9: main (in /home/enes/Desktop/Shell/shell)
==6768==
==6768== Invalid write of size 1
==6768== at 0x4EA8C80: _IO_getline_info (iogetline.c:77)
==6768== by 0x4EA7B7C: fgets (iofgets.c:53)
==6768== by 0x400EC9: main (in /home/enes/Desktop/Shell/shell)
==6768== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6768==
==6768==
==6768== Process terminating with default action of signal 11 (SIGSEGV)
==6768== Access not within mapped region at address 0x0
==6768== at 0x4EA8C80: _IO_getline_info (iogetline.c:77)
==6768== by 0x4EA7B7C: fgets (iofgets.c:53)
==6768== by 0x400EC9: main (in /home/enes/Desktop/Shell/shell)
==6768== If you believe this happened as a result of a stack
==6768== overflow in your program's main thread (unlikely but
==6768== possible), you can try to increase the size of the
==6768== main thread stack using the --main-stacksize= flag.
==6768== The main thread stack size used in this run was 8388608.
==6768==
==6768== HEAP SUMMARY:
==6768== in use at exit: 0 bytes in 0 blocks
==6768== total heap usage: 2 allocs, 2 frees, 2,048 bytes allocated
==6768==
==6768== All heap blocks were freed -- no leaks are possible
==6768==
==6768== For counts of detected and suppressed errors, rerun with: -v
==6768== Use --track-origins=yes to see where uninitialised values come from
==6768== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
Syscall param rt_sigaction(act->sa_mask) points to uninitialised byte(s)
您需要完全初始化sigaction
结构,否则它包含不确定的值。阅读这些(可能通过 sigaction()
函数调用)很可能会导致 Undefined Behaviour,由此可能发生任何事情。
修复此更改
struct sigaction act;
成为
struct sigaction act = {0};
可能不是您面临的问题,但仍然是:
不保存 从信号处理程序调用 printf()
函数家族的任何成员。
甚至更多:可以从信号处理程序安全调用的函数集(非常)有限。有关完整列表,请参阅 chapter 2.4.3 on this page。
修复此更改
printf("OK.\n");
成为
write(STDERR_FILENO, "OK.\n", sizeof "OK.\n" -1);
或类似的。根据上面链接的列表,write()
保存为从信号处理程序调用。
==6768== Use of uninitialised value of size 8
==6768== at 0x4EA8C80: _IO_getline_info (iogetline.c:77)
==6768== by 0x4EA7B7C: fgets (iofgets.c:53)
调用 fgets()
究竟出了什么问题,我们无法判断,因为您没有向我们展示相关代码。
我试图在 C 中实现一个简单的 Unix shell。但是,我无法使用 sigaction 实现后台进程功能。我的代码结构如下:
int main() {
struct sigaction act;
act.sa_handler = handler;
sigaction(SIGCHLD, &act, 0);
while(1) {
parseCommand();
execCommand();
}
}
此外,在我的 execCommand 函数中,结构如下:
if (fork()) {
if (!isBackground) {
wait(&child_status);
}
else
printf("Background process\n");
}
else
... // Command execution...
我的处理程序如下所示:
void handler(int s) {
while (waitpid(-1, NULL, WNOHANG) > 0) {
}
printf("OK.\n");
}
但这种结构损害了我的整个实施。即使是前台进程也无法正常工作。当我执行前台命令时,它给出:
Segmentation fault (core dumped)
当我执行后台命令时,它给出:
Bus error (core dumped)
那么,我该如何解决这个问题呢?
提前致谢...
编辑:当我用 valgrind 调试我的代码时,它给出以下内容:
==6768== Memcheck, a memory error detector
==6768== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6768== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==6768== Command: ./shell
==6768==
==6768== Syscall param rt_sigaction(act->sa_mask) points to uninitialised byte(s)
==6768== at 0x4E6F5AE: __libc_sigaction (sigaction.c:62)
==6768== by 0x400E90: main (in /home/enes/Desktop/Shell/shell)
==6768== Address 0xffefff908 is on thread 1's stack
==6768==
==6768== Syscall param rt_sigaction(act->sa_flags) points to uninitialised byte(s)
==6768== at 0x4E6F5AE: __libc_sigaction (sigaction.c:62)
==6768== by 0x400E90: main (in /home/enes/Desktop/Shell/shell)
==6768== Address 0xffefff8f8 is on thread 1's stack
==6768==
> ls
==6768== Use of uninitialised value of size 8
==6768== at 0x4EA8C80: _IO_getline_info (iogetline.c:77)
==6768== by 0x4EA7B7C: fgets (iofgets.c:53)
==6768== by 0x400EC9: main (in /home/enes/Desktop/Shell/shell)
==6768==
==6768== Invalid write of size 1
==6768== at 0x4EA8C80: _IO_getline_info (iogetline.c:77)
==6768== by 0x4EA7B7C: fgets (iofgets.c:53)
==6768== by 0x400EC9: main (in /home/enes/Desktop/Shell/shell)
==6768== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6768==
==6768==
==6768== Process terminating with default action of signal 11 (SIGSEGV)
==6768== Access not within mapped region at address 0x0
==6768== at 0x4EA8C80: _IO_getline_info (iogetline.c:77)
==6768== by 0x4EA7B7C: fgets (iofgets.c:53)
==6768== by 0x400EC9: main (in /home/enes/Desktop/Shell/shell)
==6768== If you believe this happened as a result of a stack
==6768== overflow in your program's main thread (unlikely but
==6768== possible), you can try to increase the size of the
==6768== main thread stack using the --main-stacksize= flag.
==6768== The main thread stack size used in this run was 8388608.
==6768==
==6768== HEAP SUMMARY:
==6768== in use at exit: 0 bytes in 0 blocks
==6768== total heap usage: 2 allocs, 2 frees, 2,048 bytes allocated
==6768==
==6768== All heap blocks were freed -- no leaks are possible
==6768==
==6768== For counts of detected and suppressed errors, rerun with: -v
==6768== Use --track-origins=yes to see where uninitialised values come from
==6768== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
Syscall param rt_sigaction(act->sa_mask) points to uninitialised byte(s)
您需要完全初始化sigaction
结构,否则它包含不确定的值。阅读这些(可能通过 sigaction()
函数调用)很可能会导致 Undefined Behaviour,由此可能发生任何事情。
修复此更改
struct sigaction act;
成为
struct sigaction act = {0};
可能不是您面临的问题,但仍然是:
不保存 从信号处理程序调用 printf()
函数家族的任何成员。
甚至更多:可以从信号处理程序安全调用的函数集(非常)有限。有关完整列表,请参阅 chapter 2.4.3 on this page。
修复此更改
printf("OK.\n");
成为
write(STDERR_FILENO, "OK.\n", sizeof "OK.\n" -1);
或类似的。根据上面链接的列表,write()
保存为从信号处理程序调用。
==6768== Use of uninitialised value of size 8 ==6768== at 0x4EA8C80: _IO_getline_info (iogetline.c:77) ==6768== by 0x4EA7B7C: fgets (iofgets.c:53)
调用 fgets()
究竟出了什么问题,我们无法判断,因为您没有向我们展示相关代码。