SIGINT 信号在写入管道期间丢失

2024-01-26

我有一个程序,使用 pcap_dump 函数将使用 libpcap 收集的 pcap 数据转储到 stdout,其中 stdout 作为 FILE *。 SIGINT 需要进行一些清理,因此我使用 sigaction() 来处理它。从 shell 执行时效果很好。

然而,这个程序是打算被另一个程序调用的,这似乎不起作用。这个“调用者”程序调用 Pipe(),然后调用 fork(),然后子进程的 stdout 文件描述符被关闭,并替换为管道的写入端。最后,在子进程中执行前述的pcap程序。这样pcap数据就通过管道写入调用者程序。这也很好用。但是,当我在子进程写入管道时向其发送 SIGINT 时(嗯,pcap 程序认为它正在写入 stdout,但其文件描述符已更改),信号似乎被丢弃,并且信号处理函数根本不会被叫到。

这是为什么?如果我将 pcap 数据写入 stderr 或文件,SIGINT 永远不会被丢弃。仅当写入管道时。

以下是我们如何设置管道/分叉/执行:

int fd[2];

//Create pipe
pipe(fd);

pid = fork(); //We forked a child

if(pid == 0){ //We are the child now

    close(1); //close child's stdout

    dup(fd[1]); //duplicate child's stdout to the write end of the pipe

    close( fd[0]); //close unused file descriptors
    close( fd[1]);

    //Load the new program
    execlp("./collectraw", "collectraw", NULL);

    perror("Exec");
    exit(127); //Should never get called but we leave it so the child
    //doesnt accidently keep executing
}
else{ //We are the parent

    //Set up the file descriptors
    close(fd[1]);
}

然后要杀死孩子,我们使用:

kill( pid, SIGINT);

在子进程中,pcap_loop() 的回调函数可以很简单:

void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){
    write(1,"<pretend this is like a thousand zeros>",1000); //write to stdout, which is really a pipe
}

我们基本上总是会丢弃 SIGINT。顺便说一句,有很多数据包需要捕获,因此可以很安全地假设它几乎总是在回调函数中。

但如果我们从

write(1,... ); //write to stdout, which is really a pipe

to

write(2,...); //write to stderr, or writing to a file would work too

然后一切又变得美好了。

为什么我们的 SIGINT 在写入管道期间会被丢弃?

谢谢你的帮助。

编辑:孩子的 SIGINT 处理程序根本没有被调用,但原因并不是孩子的问题,而是父母的问题。我曾经这样杀死孩子:

if( kill( pid, SIGINT) == -1){
    perror("Could not kill child");
}
close(pipefd);
fprintf(stdout, "Successfully killed child\n");

这曾经是我们的 SIGCHLD 处理程序:

void handlesigchild(int sig) {
    wait();

    printf("Cleaned up a child\n");
}

因此,正如已接受的答案中所述,立即关闭管道会导致我们的孩子在处理 SIGINT 之前以 SIGPIPE 退出。我们刚刚将 close(pipefd) 移至 SIGCHLD 处理程序,现在它可以工作了。


您没有显示足够的代码来了解发生了什么。你应该总是尝试构建一个SSCCE http://sscce.org如果您希望人们能够对您的程序发表评论,请发布该内容。

最佳猜测:您的父级在发送信号后退出,关闭管道的读取端。这会导致客户端在有机会处理 SIGINT 之前立即退出并发出 SIGPIPE。尝试对 SIGPIPE 进行清理,或者忽略 SIGPIPE。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SIGINT 信号在写入管道期间丢失 的相关文章

  • 无法将匿名方法转换为类型“System.Windows.Threading.DispatcherPriority”,因为它不是委托类型

    谁能解释我需要做什么才能克服这个错误 无法将匿名方法转换为类型 System Windows Threading DispatcherPriority 因为它不是委托类型 private void Test object sender ba
  • 有没有办法为向量采用内存资源?

    我已经开始在我的项目中使用 pmr allocators 并且我已经看到使用它们带来了很多性能提升和优势 我使用的分配器与我在下面的简单示例中展示的非常相似 include
  • 哪些 iomanip 操纵器具有“粘性”?

    我最近在创建一个stringstream由于我错误地假设std setw 会影响每次插入的字符串流 直到我明确更改它 然而 插入后它总是被取消设置 With timestruct with value of Oct 7 9 04 AM st
  • 除了第一列之外,Gridview 行可点击?

    我使用以下代码使 gridview 的整行可单击 protected void gridMSDS RowDataBound object sender GridViewRowEventArgs e if e Row RowType Data
  • 如何使用 saxon 将文档类型参数传递给 xslt?

    对于发送原子数据类型将使用类似 transformer SetParameter new QName customXml new XdmAtomicValue true 如何将 XML Node 作为参数从 C 传递给 XSLT 你能帮我么
  • 根据另一个列表的内容对列表进行排序

    我有一个包含整数列表的列表和另一个包含同时包含整数和字符串的类的列表 我想做的是按字母顺序对列表进行排序 将第一个列表中存在的条目放在前面 这是我的代码和预期输出 using System using System Collections
  • 使用inotify监控文件

    我正在使用 inotify 来监视本地文件 例如使用 root temp inotify add watch fd root temp mask 删除该文件后 程序将被阻止read fd buf bufSize 功能 即使我创建一个新的 r
  • C++ 中的字符串到 LPCWSTR

    我正在尝试从字符串转换为 LPCWSTR 我使用多位 1 例如 LPCWSTR ToLPCWSTR string text LPCWSTR sw LPCWSTR text c str return sw 2 返回中文字符 LPCWSTR T
  • ASP .NET MVC 5 - 客户地址一对一关系

    我在这里查看了论坛 实际上发现了一些类似的问题 但不是相同的问题 类似的解决方案没有给我正确的答案 我正在使用实体框架和代码优先方法来处理 ASP NET MVC 5 我想建立客户 gt 地址一对一关系的模型 我建模的是 客户等级 publ
  • 超时时杀死或终止子进程?

    我想尽可能快地重复执行子进程 然而 有时这个过程会花费太长的时间 所以我想杀死它 我使用 signal signal 如下所示 ppid pipeexe pid signal signal signal SIGALRM stop handl
  • 接口中的私有成员

    是否可以在 NET 接口中创建私有成员 我听说现在可以了 但我的 IDE 拒绝了 public interface IAnimal void SetDefaultName string name ChangeName name privat
  • 如何在单独的类库中管理客户端上下文对象?

    我正在尝试创建一个库 类库 对于共享点 它将拥有所有共享点 dll 来与共享点服务器交互上传文件 文档并创建文档库和文档集 现在这个库可以被使用客户端 例如 Web 应用程序 asp net webform 或 mvc 或控制台应用程序或
  • 为什么long long 2147483647 + 1 = -2147483648? [复制]

    这个问题在这里已经有答案了 为什么这段代码不打印相同的数字 long long a b a 2147483647 1 b 2147483648 printf lld n a printf lld n b 我知道int变量的最大数量是2147
  • 在 C# 中使用 as 关键字与泛型类型发生冲突的编译时行为

    当尝试对无法转换为的非泛型类型使用 C as 关键字时 编译器会给出无法转换类型的错误 但是 当对泛型类型使用 as 关键字时 编译器不会给出错误 public class Foo public class Bar
  • 在 C# 4.0 中,是否可以从泛型类型参数派生类?

    我一直在尝试这个 但我似乎无法弄清楚 我想做这个 public abstract class SingletonType
  • 如何在OpenGL中像这样绘制连接的带状线

    我想用以下方式绘制一系列连接线 GL LINE STRIP 我尝试过自己编写代码 但没有得到想要的结果 所以我来到这里 帮助我找出我错在哪里 这里我只给出我的draw 函数 glBegin GL LINE STRIP glVertex2f
  • 第一个随机数始终小于其余随机数

    我碰巧注意到 在 C 中 使用 std rand 方法调用的第一个随机数大多数时候都明显小于第二个随机数 关于 Qt 实现 第一个几乎总是小几个数量级 qsrand QTime currentTime msec qDebug lt lt q
  • STL 向量、迭代器和插入 (C++)

    我有一个将向量的迭代器传递到的方法 在这个方法中 我想向向量中添加一些元素 但我不确定当只有迭代器时这是否可行 void GUIComponentText AddAttributes vector
  • 访问 Visual Studio 扩展中的当前代码窗格

    我正在编写一个 Visual Studio 2010 扩展 在代码视图中带有右键单击菜单 我希望能够从菜单项事件处理程序检查当前代码 但无法在对象模型中找到执行此操作的位置 如何在 Visual Studio 扩展中访问当前窗口中的代码 E
  • GetActiveObject() 与 GetObject() -- MK_E_UNAVAILABLE 错误

    All 我在将一些 VBA 代码转换为 C 时遇到一些问题 我们有一个充当本地 COM 服务器的第 3 方应用程序 在我们使用的VBA代码中获取对象 获取对现有对象的引用 e g Set appHandle GetObject ProgId

随机推荐