微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

boost::interprocess 消息队列不删除

如何解决boost::interprocess 消息队列不删除

使用 boost::interprocess 消息队列时,我在删除队列时遇到了问题,希望有人能解释这种行为,或者纠正我的误解。 我在 Linux RHEL7 机器上。我有两个进程,一个创建并提供队列,另一个打开消息队列并从中读取。为清楚起见,首先启动初始进程,然后是从队列中读取/删除消息的第二个进程。 创建的那个是create_only_t。如果它已经存在,我希望它失败。然而,第一个队列的创建总是失败。它抛出的特定异常是 File exists

当切换到 open_or_create_t 队列时,它工作正常。我接受了这些信息,因为我没有正确清理它,所以我确保在尝试创建队列之前以及在该过程完成发送所有消息之后尝试删除队列。 如果删除成功,我会记录。我的假设之一是,如果 remove 返回 true,则意味着它成功删除了队列。 remove 的 boost 文档写道:“从系统中删除消息队列。错误时返回 false。”,我不确定是否真的只是意味着它成功地“尝试”了删除它。进一步查看另一个 Boost Inprocess pdf 后,它解释说:

如果共享内存不存在、文件处于打开状态或文件仍然是由其他进程映射的内存,则删除操作可能会失败并返回 false

无论哪种情况,我觉得如果队列总是返回 true,我会希望队列被删除,这就是我目前的情况。 仍然在尝试执行 'create_t' 消息队列时它会继续失败,但 'open_or_create_t' 仍然有效。

我很难理解这种行为,因此我还尝试在尝试初始化 create_t 队列之前连续两次删除消息队列以查看第二个队列是否会失败/返回 false,但是两者都返回 true (这不是我根据文档所说的预期)。如果第一次删除成功,则意味着第二次删除应该失败,因为不再存在消息队列。

我附上了我的创建流程代码片段。我会注意到,这个错误发生在没有运行“打开进程”的情况下。

也许我遗漏了一些明显的东西,提前致谢。

try {
    bool first_removal = remove(msg_queue_name);
    if (first_removal) {
      log_info("first removal - true"); // this log always prints
      bool second_removal = remove(msg_queue_name);
      if (second_removal ) {
        log_info("removal was again true"); // this also always prints
      } else {
        log_info("second removal - false");
      }
    } else {
      log_info("did not remove queue before creation");
    }

    log_info("attempting to initialize msg queue");
    message_queue mq(ooc,msg_queue_name,max_num_msgs,max_msg_size); // this is where it will fail (File exists)
  
    while(1) {
      // insertion logic,but does not get here
    }
  } catch ( interprocess_exception& err ) {
    log_error(err.what()); // File exists
    bool removal_after_failure = remove(msg_queue_name);
    if (removal_after_failure) {
      log_info("Message queue was successfully removed"); // always logs here after every failure
    } else {
      log_warn("Message queue was NOT removed");
    }
  }

解决方法

它对我有用。

然后我就明白了。你可能是using namespace。别。为此:

bool first_removal = remove(msg_queue_name);

这不会调用您期望的函数。它调用 ::remove from the C standard library

简单地限定您的通话:

bool first_removal = message_queue::remove(msg_queue_name);

措施

你可以做什么:

  • 编写卫生代码
    • 避免使用命名空间指令
    • 避免 ADL 陷阱
    • 使用警告(至少 -Wall -Wextra -pedantic)
    • 使用短绒。见下文
  • 检查你的假设(简单地进入调试器就会告诉你发生了什么)

短绒?

例如clang-tidy 报道:

test.cpp|27 col 30| warning: implicit conversion 'int' -> bool [readability-implicit-bool-conversion]
||         bool first_removal = remove(msg_queue_name);

建议写:

bool first_removal = remove(msg_queue_name) != 0;

这让我意识到有些东西可能很可疑。

修复

稍后修复了几个这些代码并运行了

生活在 Coliru

#include <boost/interprocess/ipc/message_queue.hpp>
#include <chrono>
#include <iostream>

namespace bip = boost::interprocess;
using bip::message_queue;
using bip::interprocess_exception;
using namespace std::chrono_literals;
using C = std::chrono::high_resolution_clock;

static constexpr char const* msg_queue_name = "my_mq";
static constexpr bip::open_or_create_t ooc;
static constexpr auto max_num_msgs = 10;
static constexpr auto max_msg_size = 10;

static auto log_impl = [start=C::now()](auto severity,auto const& ... args) {
    std::clog << severity << " at " << std::fixed << (C::now()-start)/1.ms << "ms ";
    (std::clog << ... << args) << std::endl;
};

static auto log_error = [](auto const& ... args) { log_impl("error",args...); };
static auto log_warn = [](auto const& ... args) { log_impl("warn",args...); };
static auto log_info = [](auto const& ... args) { log_impl("info",args...); };

int main() {
    try {
        bool first_removal = message_queue::remove(msg_queue_name);
        if (first_removal) {
            log_info("first removal - true"); // this log always prints
            bool second_removal = message_queue::remove(msg_queue_name);
            if (second_removal) {
                log_info("removal was again true"); // this also always prints
            } else {
                log_info("second removal - false");
            }
        } else {
            log_info("did not remove queue before creation");
        }

        log_info("attempting to initialize msg queue");
        message_queue mq(
            ooc,msg_queue_name,max_num_msgs,max_msg_size); // this is where it will fail (File exists)

        log_info("Start insertion");
    } catch (interprocess_exception& err) {
        log_error(err.what()); // File exists
        bool removal_after_failure = message_queue::remove(msg_queue_name);
        if (removal_after_failure) {
            log_info("Message queue was successfully removed"); // always logs
                                                                // here after
                                                                // every failure
        } else {
            log_warn("Message queue was NOT removed");
        }
    }
}

在 Coliru 上打印:

info at 22.723521ms did not remove queue before creation
info at 22.879425ms attempting to initialize msg queue
error at 23.098989ms Function not implemented
warn at 23.153540ms Message queue was NOT removed

在我的系统上:

info at 0.148484ms first removal - true
info at 0.210316ms second removal - false
info at 0.232181ms attempting to initialize msg queue
info at 0.299645ms Start insertion
./sotest 
info at 0.099407ms first removal - true
info at 0.173156ms second removal - false
info at 0.188026ms attempting to initialize msg queue
info at 0.257117ms Start insertion

当然,现在您的逻辑可以大大简化:

Live On Coliru

int main() {
    try {
        bool removal = message_queue::remove(msg_queue_name);
        log_info("attempting to initialize msg queue (removal:",removal,")");
        message_queue mq(
            ooc,max_msg_size); // this is where it will fail (File exists)

        log_info("insertion");
    } catch (interprocess_exception const& err) {
        bool removal = message_queue::remove(msg_queue_name);
        log_info(err.what()," (removal:",")");
    }
}

打印

info at 0.462333ms attempting to initialize msg queue (removal:false)
info at 0.653085ms Function not implemented (removal:false)

info at 0.097283ms attempting to initialize msg queue (removal:true)
info at 0.239138ms insertion

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?