亲子信号沟通陷入僵局

2024-01-08

我已经实现了两个程序(parent.cpp,child.c),它们应该通过信号进行通信,以交替方式无限期地工作。然而,由于某种原因,程序在随机的时间后进入死锁,我无法弄清楚为什么(发送给父进程的信号似乎在没有执行信号处理程序的情况下被丢弃;因此,两者都等待来自其他进程的信号)。

程序执行的步骤:首先,初始化父进程,生成子进程并等待子进程的初始化(参见.LLVMFuzzerInitialize在parent.cpp中)。然后,进入一个循环,并且在每次迭代中LLVMFuzzerTestOneInput叫做。这里,(1) 父进程将数据写入子进程的 stdin,(2) 通过 SIGUSR2 唤醒子进程,(3) 子进程处理数据,以及 (4) 通过 SIGUSR1 唤醒父进程。

在 Linux 上,parent通常在几千次迭代后停止parent_main在大多数运行中无限期地运行(尽管有时它也会在几万次迭代后停止)。在 Mac 上,这两个程序都会在几秒钟后停止。

下面是一个由parent.cpp、child.c 和 Makefile 组成的最小工作示例:

// parent.cpp
#include <cstdlib>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>

#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

static volatile sig_atomic_t signal_received = 0;

static pid_t child_pid = -1;
static int fdin[2], fdout[2];

void handleSIGUSR1(int signo, siginfo_t *info, void *context)
{
    if (child_pid == info->si_pid)
        signal_received = 1;
}

void handleSIGCHLD(int signo, siginfo_t *info, void *context)
{
    exit(EXIT_FAILURE);
}

void initPipes()
{
    if (pipe(fdin) < 0)
        exit(EXIT_FAILURE);

    if (pipe(fdout) < 0)
        exit(EXIT_FAILURE);
}

void initSignalHandler()
{
    struct sigaction act = {0};

    act.sa_flags = SA_SIGINFO | SA_RESTART;

    {
        act.sa_sigaction = &handleSIGUSR1;
        sigaction(SIGUSR1, &act, NULL);
    }

    {
        act.sa_sigaction = &handleSIGCHLD;
        sigaction(SIGCHLD, &act, NULL);
    }
}

void waitForChild()
{
    sigset_t mask, oldmask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGUSR1);

    if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1)
        exit(EXIT_FAILURE);

    while (signal_received == 0)
    {
        sigsuspend(&oldmask);
    }
    signal_received = 0;
    if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
        exit(EXIT_FAILURE);
}

extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv)
{
    initPipes();
    initSignalHandler();

    child_pid = fork();
    if (child_pid < 0)
        exit(EXIT_FAILURE);

    if (child_pid == 0)
    {
        if (dup2(fdin[0], STDIN_FILENO) < 0)
            exit(EXIT_FAILURE);

        if (dup2(fdout[1], STDOUT_FILENO) < 0)
            exit(EXIT_FAILURE);

        char file[] = "./child";
        char *const argv[] = {"child", NULL};
        char *env[] = {NULL};

        execve(file, argv, env);
        exit(EXIT_FAILURE);
    }

    // Waiting until child is initialized
    waitForChild();

    return 0;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
    static int iteration = 0;
    std::cout << "parent.iteration: " << iteration++ << std::endl;

    char buffer[1024];
    write(fdin[1], buffer, 1024);

    kill(child_pid, SIGUSR2);

    waitForChild();

    return 0;
}

#ifdef DEFINE_MAIN
int main(int argc, char **argv)
{
    LLVMFuzzerInitialize(&argc, &argv);
    for (;;)
    {
        uint8_t buffer[1];
        LLVMFuzzerTestOneInput(buffer, 1);
    }
}
#endif
// child.c
#include <stdio.h>
#include <signal.h>
#include <inttypes.h>
#include <unistd.h>
#include <stdlib.h>

static volatile sig_atomic_t signal_received = 0;

void handleSIGUSR2(int signo, siginfo_t *info, void *context)
{
    signal_received = 1;
}

void waitForParent()
{
    sigset_t mask, oldmask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGUSR2);

    if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1) {
        perror("sigprocmask-block (child)");
        exit(EXIT_FAILURE);
    }
    while (signal_received == 0)
    {
        sigsuspend(&oldmask);
    }
    signal_received = 0;
    if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) {
        perror("sigprocmask-unblock (child)");
        exit(EXIT_FAILURE);
    };
}

void readPackage()
{
    uint8_t buffer[1024];
    read(0, buffer, 1024);
}

int main(int argc, char **argv)
{
    struct sigaction act = {0};
    act.sa_flags = SA_SIGINFO | SA_RESTART;
    act.sa_sigaction = &handleSIGUSR2;
    sigaction(SIGUSR2, &act, NULL);

    // Notify parent about initialization
    kill(getppid(), SIGUSR1);

    while (1)
    {
        static int iteration = 0;

        waitForParent();

        fprintf(stderr, "child.iteration: %d\n", iteration++);
        readPackage();

        kill(getppid(), SIGUSR1);
    }
}
all: child parent parent_main

child: child.c
    clang -fsanitize=address $< -o $@

parent: parent.cpp
    clang++ -fsanitize=fuzzer,address $< -o $@

parent_main: parent.cpp
    clang++ -DDEFINE_MAIN $< -o $@

Edit:

在Linux(archlinux 5.19.11,clang版本:14.0.6)上,我还无法得到parent_main再次陷入死锁状态,但是我用了strace -f ./parent(为简洁起见,我只显示最后两次迭代):

[pid 167430] write(1, "parent.iteration: 1698\n", 23) = 23
[pid 167430] write(4, "0\0\0\0 `\0\0`\204\10\334\376\177\0\0\20\205\10\334\376\177\0\0\352\213\216\200\337U\0\0"..., 1024) = 1024
[pid 167430] kill(167431, SIGUSR2)      = 0
[pid 167431] <... rt_sigsuspend resumed>) = ? ERESTARTNOHAND (To be restarted if no handler)
[pid 167430] rt_sigprocmask(SIG_BLOCK, [USR1],  <unfinished ...>
[pid 167431] --- SIGUSR2 {si_signo=SIGUSR2, si_code=SI_USER, si_pid=167430, si_uid=0} ---
[pid 167430] <... rt_sigprocmask resumed>[], 8) = 0
[pid 167431] rt_sigreturn({mask=[USR2]} <unfinished ...>
[pid 167430] rt_sigsuspend([], 8 <unfinished ...>
[pid 167431] <... rt_sigreturn resumed>) = -1 EINTR (Interrupted system call)
[pid 167431] rt_sigprocmask(SIG_UNBLOCK, [USR2], NULL, 8) = 0
[pid 167431] write(2, "child.iteration: 1698\n", 22child.iteration: 1698
) = 22
[pid 167431] read(0, "0\0\0\0 `\0\0`\204\10\334\376\177\0\0\20\205\10\334\376\177\0\0\352\213\216\200\337U\0\0"..., 1024) = 1024
[pid 167431] getppid()                  = 167430
[pid 167431] kill(167430, SIGUSR1 <unfinished ...>
[pid 167430] <... rt_sigsuspend resumed>) = ? ERESTARTNOHAND (To be restarted if no handler)
[pid 167431] <... kill resumed>)        = 0
[pid 167430] --- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, si_pid=167431, si_uid=0} ---
[pid 167431] rt_sigprocmask(SIG_BLOCK, [USR2],  <unfinished ...>
[pid 167430] rt_sigreturn({mask=[USR1]} <unfinished ...>
[pid 167431] <... rt_sigprocmask resumed>[], 8) = 0
[pid 167430] <... rt_sigreturn resumed>) = -1 EINTR (Interrupted system call)
[pid 167431] rt_sigsuspend([], 8 <unfinished ...>
[pid 167430] rt_sigprocmask(SIG_UNBLOCK, [USR1], NULL, 8) = 0
[pid 167430] clock_gettime(CLOCK_REALTIME, {tv_sec=1665498102, tv_nsec=952308734}) = 0
[pid 167430] clock_gettime(CLOCK_REALTIME, {tv_sec=1665498102, tv_nsec=952354900}) = 0


[pid 167430] write(1, "parent.iteration: 1699\n", 23) = 23
[pid 167430] write(4, "0\0\0\0 `\0\0`\204\10\334\376\177\0\0\20\205\10\334\376\177\0\0\352\213\216\200\337U\0\0"..., 1024) = 1024
[pid 167430] kill(167431, SIGUSR2)      = 0
[pid 167431] <... rt_sigsuspend resumed>) = ? ERESTARTNOHAND (To be restarted if no handler)
[pid 167430] rt_sigprocmask(SIG_BLOCK, [USR1],  <unfinished ...>
[pid 167431] --- SIGUSR2 {si_signo=SIGUSR2, si_code=SI_USER, si_pid=167430, si_uid=0} ---
[pid 167430] <... rt_sigprocmask resumed>[], 8) = 0
[pid 167431] rt_sigreturn({mask=[USR2]} <unfinished ...>
[pid 167430] rt_sigsuspend([], 8 <unfinished ...>
[pid 167431] <... rt_sigreturn resumed>) = -1 EINTR (Interrupted system call)
[pid 167431] rt_sigprocmask(SIG_UNBLOCK, [USR2], NULL, 8) = 0
[pid 167431] write(2, "child.iteration: 1699\n", 22child.iteration: 1699
) = 22
[pid 167431] read(0, "0\0\0\0 `\0\0`\204\10\334\376\177\0\0\20\205\10\334\376\177\0\0\352\213\216\200\337U\0\0"..., 1024) = 1024
[pid 167431] getppid()                  = 167430
[pid 167432] <... clock_nanosleep resumed>0x7ff1859f8de0) = 0
[pid 167431] kill(167430, SIGUSR1 <unfinished ...>
[pid 167430] <... rt_sigsuspend resumed>) = ? ERESTARTNOHAND (To be restarted if no handler)
[pid 167432] --- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, si_pid=167431, si_uid=0} ---
[pid 167431] <... kill resumed>)        = 0
[pid 167430] rt_sigsuspend([], 8 <unfinished ...>
[pid 167431] rt_sigprocmask(SIG_BLOCK, [USR2],  <unfinished ...>
[pid 167432] rt_sigreturn({mask=[]} <unfinished ...>
[pid 167431] <... rt_sigprocmask resumed>[], 8) = 0
[pid 167432] <... rt_sigreturn resumed>) = 0
[pid 167431] rt_sigsuspend([], 8 <unfinished ...>

看起来虽然孩子叫kill(1674310, SIGUSR1),信号到达 libFuzzer 进程(pid:167432)...我不知道从这里去哪里?


None

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

亲子信号沟通陷入僵局 的相关文章

  • 如何检查图像对象与资源中的图像对象是否相同?

    所以我试图创建一个简单的程序 只需在单击图片框中更改图片即可 我目前只使用两张图片 所以我的图片框单击事件函数的代码 看起来像这样 private void pictureBox1 Click object sender EventArgs
  • 如何使 Windows 窗体的关闭按钮不关闭窗体但使其不可见?

    该表单有一个 NotifyIcon 对象 当用户单击 关闭 按钮时 我希望表单不关闭而是变得不可见 然后 如果用户想再次查看该表单 可以双击系统托盘中的图标 如果用户想关闭表单 可以右键单击该图标并选择 关闭 有人可以告诉我如何使关闭按钮不
  • C# 和 Javascript SHA256 哈希的代码示例

    我有一个在服务器端运行的 C 算法 它对 Base64 编码的字符串进行哈希处理 byte salt Convert FromBase64String serverSalt Step 1 SHA256Managed sha256 new S
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • C++ 子字符串返回错误结果

    我有这个字符串 std string date 20121020 我正在做 std cout lt lt Date lt lt date lt lt n std cout lt lt Year lt lt date substr 0 4 l
  • 实时服务器上的 woff 字体 MIME 类型错误

    我有一个 asp net MVC 4 网站 我在其中使用 woff 字体 在 VS IIS 上运行时一切正常 然而 当我将 pate 上传到 1and1 托管 实时服务器 时 我得到以下信息 网络错误 404 未找到 http www co
  • Newtonsoft JSON PreserveReferences处理自定义等于用法

    我目前在使用 Newtonsoft Json 时遇到一些问题 我想要的很简单 将要序列化的对象与所有属性和子属性进行比较以确保相等 我现在尝试创建自己的 EqualityComparer 但它仅与父对象的属性进行比较 另外 我尝试编写自己的
  • 如何将图像和 POST 数据上传到 Azure 移动服务 ApiController 终结点?

    我正在尝试上传图片and POST表单数据 尽管理想情况下我希望它是json 到我的端点Azure 移动服务应用 我有ApiController method HttpPost Route api upload databaseId sea
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • 需要哪个版本的 Visual C++ 运行时库?

    microsoft 的最新 vcredist 2010 版 是否包含以前的版本 2008 SP1 和 2005 SP1 还是我需要安装全部 3 个版本 谢谢 你需要所有这些
  • WCF:将随机数添加到 UsernameToken

    我正在尝试连接到用 Java 编写的 Web 服务 但有些东西我无法弄清楚 使用 WCF 和 customBinding 几乎一切似乎都很好 除了 SOAP 消息的一部分 因为它缺少 Nonce 和 Created 部分节点 显然我错过了一
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a
  • mysql-connector-c++ - “get_driver_instance”不是“sql::mysql”的成员

    我是 C 的初学者 我认为学习的唯一方法就是接触一些代码 我正在尝试构建一个连接到 mysql 数据库的程序 我在 Linux 上使用 g 没有想法 我运行 make 这是我的错误 hello cpp 38 error get driver
  • 如何在 C++ BOOST 中像图形一样加载 TIFF 图像

    我想要加载一个 tiff 图像 带有带有浮点值的像素的 GEOTIFF 例如 boost C 中的图形 我是 C 的新手 我的目标是使用从源 A 到目标 B 的双向 Dijkstra 来获得更高的性能 Boost GIL load tiif
  • 两种情况或 if 哪个更快? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我必须制作一个 非常 轻的脚本 它将接受用户的选项并调用脚本中的函数来执行一些任务 现在我可以使用 IF 和 CASE 选项 但我想知道两

随机推荐

  • 在 EmberJS 中进行 AJAX GET 和 POST 调用的正确方法

    我已经开始研究 EmberJS 并且非常喜欢它 它确实有一个学习曲线 但我相信它具有从根本上非常有意义的原则 我的问题是如何在 Ember JS 中进行 GET 和 POST 调用 我知道有模型 商店 但模型 在我看来 仅适用于特定实体的属
  • 如何在 IL 中实现 C# foreach 优化

    In this answer https stackoverflow com a 3168435 801189和这个GitHub问题 https github com dotnet roslyn issues 426 顶部项目 有一个描述f
  • gradle - 无法从 Maven 存储库中找到依赖项

    我在使用以下 build gradle 时遇到构建错误 apply plugin java apply plugin idea sourceCompatibility 1 7 version 1 0 repositories mavenLo
  • Magento - 数据未插入数据库,但id自动递增

    我正在为 Magento 开发一个新的支付模块 并且遇到了一个我无法解释的问题 验证信用卡后运行以下代码 table prefix Mage getConfig gt getTablePrefix tableName table prefi
  • cURL 错误 1:不支持的协议:https

    All 我尝试通过 PHP 的 cURL 包装器方法 HTTPS POST SOAP 请求 但不断收到以下 cURL 错误 错误 1 不支持的协议 https 有什么想法为什么会发生这种情况吗 目标 URL 很好 我可以通过命令行访问它 c
  • 如何从另一个 ViewController 修改 UITableView 的单元格

    在 VC 1 中 我有一个 UITableView 当我点击一个单元格时 我会进入 VC 2 其中显示有关该单元格的信息 我希望能够在 VC 2 中按下一个按钮 从而更改它在 VC 1 中对应的单元格的标题 但我对如何执行此操作感到困惑 我
  • 将请求参数作为 UTF-8 编码字符串传递[重复]

    这个问题在这里已经有答案了 我正在创建一个简单的登录页面 我想将登录名和密码参数作为 UTF 8 编码字符串传递 正如您在下面的代码中看到的 第一行是我将编码设置为 UTF 8 的地方 但这似乎毫无意义 因为它不起作用 当我使用带有重音符号
  • 交换活动后如何保持倒计时计时器计数?

    当我在活动之间交换时 我需要一个 countDownTimer 继续运行 我有多个活动 我将 countDownTimer 放在主活动中 但是当我交换到另一个活动并返回到主活动时 它又会从头开始重新计数 我相信是因为 countDownTi
  • 使用 pysftp 或 Paramiko,如何获得包含属性的完整目录列表?

    正如标题所示 我正在尝试获取目录中所有文件和目录的列表 包括它们的属性 我正在寻找至少名称 大小 上次修改时间 以及它是文件还是文件夹 我在 Windows 上使用 Python 3 我试过了listdir 我得到了一个没有属性的文件列表
  • java.lang.Long 和 scala.Long

    我不知道我的代码中发生了什么 日志在这里 error blahblah SampleApp scala 22 53 overloaded method value reduce with alternatives error func or
  • Oracle“总”计划成本确实低于其某些要素

    我不明白为什么有时一个计划的总成本可能很小 但查看计划内部我们会发现巨大的成本 确实查询速度很慢 有人能给我解释一下吗 这是一个例子 显然 成本较高的部分来自主选择中的一个字段 该字段在子视图上执行 listagg 并且该子视图的连接条件包
  • 在运行时创建XmlRpcUrl接口

    目前 我正在使用 xml rpc net 接口通过以下语句静态创建 XML RPC XmlRpcUrl http dillieodigital wordpress com xmlrpc php public interface ICSBlo
  • DLLImport 在哪里查找非托管 DLL?

    一个简单的问题 在 Net 中声明 DLLImport 属性时 运行时在哪里寻找解决该 DLL 依赖关系的方法 我是否必须转储 DLL 和所有itsbin 文件夹中的依赖项 我认为它的工作方式与 LoadLibrary 类似 Maybe 使
  • 如何比较 PHAsset 和 UIImage

    我已经转换了一些PHAsset to UIImage PHImageManager manager PHImageManager defaultManager manager requestImageForAsset asset targe
  • 隐藏页面中的div并使其仅在打印引导程序3 MVC 5上可见

    有一个网页向用户显示信息 如果用户决定打印它 我想包含屏幕上不需要的附加信息 但在打印时会很有帮助 为了实现这种行为 我试图做一个div仅在打印时可见 但它并没有起作用 div class visible print hidden lg h
  • 如何构建卡方分布表

    我想在 python 中生成一个卡方分布表作为概率水平和自由度的函数 给定已知的卡值和自由度 如何计算概率是这样的 In 44 scipy stats chisqprob 5 991 2 Out 44 0 05001161502657908
  • 在 git rebase -i 中删除提交不会减少 .git 文件夹的大小

    我有一个 git 存储库 其中 git文件夹是7MB 然后我添加并提交了一个 exe 文件 该文件是16MB其次是 git gc aggressive git prune 经过上述我的 git文件夹现在是23MB 接下来我做了一个git r
  • sklearn Kfold 访问单折叠而不是 for 循环

    使用 cross validation KFold n n folds folds 之后 我想访问索引以进行单折叠的训练和测试 而不是遍历所有折叠 那么我们来看一下示例代码 from sklearn import cross validat
  • 有没有一种方法可以在不使用暂存缓冲区的情况下更新纹理?

    我正在与https vulkan tutorial com https vulkan tutorial com 深度缓冲代码作为基础 进行了一些更改以每帧更新命令缓冲区 我正在使用一种粗略的方法来检查 fps 不确定它到底有多准确 但我正在
  • 亲子信号沟通陷入僵局

    我已经实现了两个程序 parent cpp child c 它们应该通过信号进行通信 以交替方式无限期地工作 然而 由于某种原因 程序在随机的时间后进入死锁 我无法弄清楚为什么 发送给父进程的信号似乎在没有执行信号处理程序的情况下被丢弃 因