我正在做一个测试,有人问我如何让“读”睡眠或“写”停止进程。
对于后者,我不明白为什么我的sigpipe确实被提升了,但并没有停止这个过程:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#define READING 0
#define WRITING 1
#define DESCRIPTOR_COUNT 2
void signal_handler(int signal){
printf("sigpipe received\n");
}
int main(void)
{
int tube[DESCRIPTOR_COUNT];
pipe(tube);
// signal(SIGPIPE, signal_handler);
close(tube[READING]);
if(write(tube[WRITING], "message", 8)<0)
if(errno==EPIPE)
printf("EPIPE returned\n");
printf("123");
return EXIT_SUCCESS;
}
不带信号的()(带引号)
带signal() (未加引号)的
确实收到了SIGPIPE,但是在我不处理它的情况下,进程应该停止,但是因为我可以写"123“,这意味着进程没有停止。为什么?
另外,我在Fedora 28上,我使用的是代码块17.12。
SIGPIPE被忽略了吗?原因?
解决方案-
struct sigaction action;
action.sa_handler = SIG_DFL;
sigaction(SIGPIPE, &action, 0);
用它替换signal()
将具有预期的默认行为!
编辑我现在已经将标题从"SIGPIPE不停止进程“更改为”为什么默认SIGPIPE处理程序被更改?“
======================================================
应答
在与来自代码块的人交谈之后,代码块使用wxWidgets,并且在linux (这里是fedora 28 )上,wxWidgets使用gtk库,正如Mark Plotnick在注释中所解释的那样,gtk改变了SIGPIPE的信号处理程序,因为代码块使用fork或exec来运行代码,所以通过代码块运行的代码会受到gtk库的影响。
发布于 2018-12-16 22:07:29
Code::Blocks不是一个编译器,只是一个集成开发环境。它(可能)运行GCC编译器。而且,对于信号处理来说,GCC编译器并不是很重要。有关更多信息,请阅读signal(7)和signal-safety(7) (禁止在信号处理程序中调用printf
,因为printf
不是异步信号安全的,因此信号处理程序中的printf("sigpipe received\n");
为undefined behavior)。信号处理主要由Linux kernel (请参阅kernel.org上的源代码)完成,其中一小部分由您的C标准库(可能是GNU glibc )处理。
它似乎改变了SIGPIPE的默认信号处理程序
这是不太可能的(而且几乎肯定是错误的)。您可以在您的程序上使用strace(1)来了解它正在做什么系统调用。
printf("123");
你忘了带\n
。请记住,stdout
通常是行缓冲的。或者你应该给fflush(3)打电话。
当您从Code::块内部运行程序时,它可以在没有终端的情况下运行。我强烈建议您在terminal emulator (参见tty(4)和pty(7))中运行您的程序。当stdout
是或不是tty时,允许C标准库使用类似isatty(3)的东西来表现不同(特别是,缓冲是不同的,请参见setvbuf(3))。阅读tty demystified和termios(3)。
您还可以尝试通过将程序的stdin、stdout、stderr重定向到文件或管道(可能使用带有bash
或zsh
的|& cat
或|& less
)或任何不是tty的内容来运行程序。
顺便说一句,Code::Blocks是free software。您可以研究它的源代码,以了解它在做什么。
还可以考虑使用stdbuf(1)以不同的缓冲操作运行您的程序。
https://stackoverflow.com/questions/53801914
复制相似问题