【问题标题】:Why is my semaphore on a forked process not being released?为什么我的分叉进程上的信号量没有被释放?
【发布时间】:2020-07-20 18:55:23
【问题描述】:

我在使用 POSIX 信号量来释放分叉进程时遇到问题。通过在forkexec 之后调用正在运行的进程的另一个实例来启动分叉进程。有时孩子会被释放,有时则不会。

这是一个名为 semaphore 的 POSIX 共享内存,奇怪的是它有时会起作用。我检查了那里的其他解决方案,但他们的解决方案对我没有帮助。

void init()
{
    ...
    sem_unlink(sem_name.c_str());

    if (parent_process)
    {
        sem_t* semaphore = sem_open(sem_name.c_str(), O_CREAT | O_RDWR, 0);
        if (SEM_FAILED == semaphore)
        {
            display_error();
        }
        sem_close(semaphore);
    }

    child_pid = fork();

    if (child_pid == -1)
    {
        display_error();
    }
    else if (child_pid == 0)
    {
        int ret = execve(program_name, args, env);
        if (ret == -1)
        {
            display_error();
        }
    }
    else
    {
        // rest of code
    }
    ...
}

我让子进程等待在另一个具有此功能的类中释放:

void wait_until_released()
{
    if (!parent_process)
    {
        sem_t* semaphore = sem_open(sem_name.c_str(), O_CREAT | O_RDWR, 0);
        if (SEM_FAILED == semaphore)
        {
            display_error();
        }

        sem_wait(semaphore);

        sem_close(semaphore);
        sem_unlink(semaphore);            
    }
}

帖子是在代码中的另一个位置完成的:

void release_child()
{
    sem_t* semaphore = sem_open(sem_name.c_str(), O_CREAT | O_RDWR, 0);
    if (SEM_FAILED == semaphore)
    {
        display_error();
    }

    if (sem_post(semaphore) != 0)
    {
        display_error();
    }

    sem_close(semaphore);
    sem_unlink(semaphore);
}

【问题讨论】:

    标签: c++ posix semaphore unlink


    【解决方案1】:

    这个问题最终发生是因为我在 POSIX 信号量上调用了sem_unlink,然后在分叉进程中对其进行了等待。当所有文件描述符都在信号量上调用sem_close 时,调用sem_unlink 会导致删除信号量。从本质上讲,这阻止了我的子进程能够使用该实例并被完全释放。

    这仅在某些情况下有效,因为有一个基本假设,即在我们调用release_child 时孩子已经在等待释放。这不能保证,这也是有时而不是一直有效的原因。如果我们在孩子调用 sem_wait 之前调用 release_child,那么我们会完全删除信号量,并且孩子会创建自己的信号量版本,并且永远不会被发布到。

    通过在第一组代码中的 if 语句之后移动 unlink 调用,我阻止了子进程在等待信号量之前移除它。此外,通过从release_childwait_until_released 函数中的sem_open 中删除O_CREAT 标志以及从release_child 函数中删除sem_unlink,我阻止了孩子创建自己的信号量。

    我想记录我看到的行为,因为那是真正给我带来问题的原因。在调试和修复这个问题的过程中,我了解到如果父级创建了信号量但没有关闭它,则子级调用sem_unlink 并创建它自己的同名版本。这让我相信原来的信号量仍然存在,但 sem_post 和/或 sem_wait 不起作用。

    因此,当您执行信号量时,请注意您的发布、等待、关闭和取消链接调用。尤其是在分叉进程方面!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2021-12-28
      • 2021-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多