繁体   English   中英

boost::interprocess_exception - 创建 shared_memory_object 时的 library_error 异常

[英]boost::interprocess_exception - library_error exception when creating shared_memory_object

在极少数情况下(实际上是在单个客户端的计算机上),下面的代码会引发异常“ library_error ”:

namespace ipc = boost::interprocess;
ipc::shared_memory_object m_shm;
...
bool initAsServer(size_t sharedMemSize)
{
    ipc::permissions perm;
    perm.set_unrestricted();

    try
    {
        m_shm = ipc::shared_memory_object(
            ipc::create_only,
            CNameGenHelper::genUniqueNameUtf8().c_str(), // static std::string genUniqueNameUtf8()
            ipc::read_write, perm);
    }
    catch(const ipc::interprocess_exception& ex)
    {
        logError("failed with exception \"%s\"", ex.what());
        return false;
    }
    ...
}

在日志文件中: [ERR] 因异常“boost::interprocess_exception::library_error”而失败

Boost v1.58,平台win32,vs13。


如果您能帮我解决这个问题,我将不胜感激。 提前谢谢你!

问题的原因是事件 ID =“6005”并且源名称为“系统”Windows 日志中的“EventLog”。 事件查看器 - Windows 日志 - 系统。 如果系统日志不包含至少一个这样的事件,则方法boost::interprocess::winapi::get_last_bootup_time()返回false并且boost::interprocess::ipcdetail::windows_bootstamp构造函数抛出异常 (使用定义 BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)。

所以似乎清除“系统”窗口事件日志就足够了,任何使用 Boost 共享内存的应用程序都将停止工作。

多么可怕的逻辑:使用 Windows 事件日志的内容。 似乎这个 boost ipc 实现错误尚未修复(boost_1_61_0)。

我针对这种情况的临时解决方法(无需重新启动计算机):

bool fixBoostIpcSharedMem6005issue() const
{
    bool result = false;

    HANDLE hEventLog = ::RegisterEventSourceA(NULL, "EventLog");
    if(hEventLog)
    {
        const char* msg = "simple boost shared memory fix for 6005";

        if(::ReportEventA(hEventLog, EVENTLOG_INFORMATION_TYPE, 0, 6005, NULL, 1, 0, &msg, NULL))
            result = true;

        ::DeregisterEventSource(hEventLog);
    }

    return result;
}

使用它并再次尝试使用 ipc::shared_memory_object :)

该问题的许多详细解释,由该库的一位作者提供: Boost interprocess: Getting boot-up time is unreliable on Windows and here: Interprocess get_last_bootup_time use of Event Log on Windows is fully unreliable

显然,一个可靠的解决方案是将预处理器常量 BOOST_INTERPROCESS_SHARED_DIR_PATH 定义为函数调用,一旦机器启动,它总是返回与字符串相同的目录路径。 例如,通过格式化文件的更新时间戳,在启动时写入。

您可以 #define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED 或 BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME 切换到基于注册表或 WMI 的启动时间检测。 或者,您可以使用 BOOST_INTERPROCESS_SHARED_DIR_PATH,但它在 Windows 上没有用,因为它使用硬编码路径。 BOOST_INTERPROCESS_SHARED_DIR_FUNC 是更好的选择,因为它允许您定义一个返回共享目录路径的函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM