提升进程间互斥量并检查放弃

2021-12-24 00:00:00 windows c++ boost

我需要围绕硬件进行进程间同步.由于此代码需要在 Windows 和 Linux 上运行,因此我将使用 Boost Interprocess 互斥锁进行包装.一切正常接受我检查互斥锁放弃的方法.这有可能发生,所以我必须为此做好准备.

I have a need for interprocess synchronization around a piece of hardware. Because this code will need to work on Windows and Linux, I'm wrapping with Boost Interprocess mutexes. Everything works well accept my method for checking abandonment of the mutex. There is the potential that this can happen and so I must prepare for it.

我在测试中放弃了互斥锁,果然,当我使用 scoped_lock 锁定互斥锁时,进程无限期地阻塞.我想出了解决这个问题的方法是在 scoped_lock 上使用超时机制(因为在谷歌上搜索解决这个问题的方法的时间很多,但由于可移植性的原因,boost 并没有做太多).

I've abandoned the mutex in my testing and, sure enough, when I use scoped_lock to lock the mutex, the process blocks indefinitely. I figured the way around this is by using the timeout mechanism on scoped_lock (since much time spent Googling for methods to account for this don't really show much, boost doesn't do much around this because of portability reasons).

事不宜迟,这就是我所拥有的:

Without further ado, here's what I have:

#include <boost/interprocess/sync/named_recursive_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>

typedef boost::interprocess::named_recursive_mutex MyMutex;
typedef boost::interprocess::scoped_lock<MyMutex> ScopedLock;

MyMutex* pGate = new MyMutex(boost::interprocess::open_or_create, "MutexName");

{
    // ScopedLock lock(*pGate); // this blocks indefinitely
    boost::posix_time::ptime timeout(boost::posix_time::microsec_clock::local_time() + boost::posix_time::seconds(10));
    ScopedLock lock(*pGate, timeout); // a 10 second timeout that returns immediately if the mutex is abandoned ?????
    if(!lock.owns()) {
        delete pGate;
        boost::interprocess::named_recursive_mutex::remove("MutexName");
        pGate = new MyMutex(boost::interprocess::open_or_create, "MutexName");
    }
}

至少,这是一个想法.三个有趣的点:

That, at least, is the idea. Three interesting points:

  • 当我不使用超时对象并且互斥锁被放弃时,ScopedLock构造函数无限期地阻塞.这是意料之中的.
  • 当我确实使用超时并且互斥锁被放弃时,ScopedLock构造函数立即返回并告诉我它不拥有互斥锁.好吧,也许这很正常,但为什么它不也等待我告诉它的 10 秒呢?
  • 当互斥锁没有被放弃并且我使用超时时,ScopedLock构造函数仍然会立即返回,告诉我它无法锁定或获取互斥锁的所有权,然后我走了通过删除互斥锁并重新制作它的动作.这根本不是我想要的.
  • When I don't use the timeout object, and the mutex is abandoned, the ScopedLock ctor blocks indefinitely. That's expected.
  • When I do use the timeout, and the mutex is abandoned, the ScopedLock ctor returns immediately and tells me that it doesn't own the mutex. Ok, perhaps that's normal, but why isn't it waiting for the 10 seconds I'm telling it too?
  • When the mutex isn't abandoned, and I use the timeout, the ScopedLock ctor still returns immediately, telling me that it couldn't lock, or take ownership, of the mutex and I go through the motions of removing the mutex and remaking it. This is not at all what I want.

那么,我在使用这些对象时遗漏了什么?也许它正盯着我的脸,但我看不到它,所以我在寻求帮助.

So, what am I missing on using these objects? Perhaps it's staring me in the face, but I can't see it and so I'm asking for help.

我还应该提到,由于该硬件的工作方式,如果进程无法在 10 秒内获得互斥锁的所有权,则该互斥锁将被放弃.事实上,我可能只等待 50 或 60 毫秒,但 10 秒是一个不错的回合".慷慨的数量.

I should also mention that, because of how this hardware works, if the process cannot gain ownership of the mutex within 10 seconds, the mutex is abandoned. In fact, I could probably wait as little as 50 or 60 milliseconds, but 10 seconds is a nice "round" number of generosity.

我正在使用 Visual Studio 2010 在 Windows 7 上进行编译.

I'm compiling on Windows 7 using Visual Studio 2010.

谢谢,安迪

推荐答案

当我不使用超时对象,并且互斥被放弃时,ScopedLock ctor 会无限期地阻塞.这是预期的

When I don't use the timeout object, and the mutex is abandoned, the ScopedLock ctor blocks indefinitely. That's expected

解决您的问题的最佳解决方案是 boost 支持强大的互斥锁.但是 Boost 目前不支持强大的互斥锁.只有一个计划来模拟强大的互斥锁,因为只有 linux 对此有本机支持.模拟仍然只是由图书馆作者 Ion Gaztanaga 计划的.检查此链接,了解 rubust 互斥锁可能被黑客入侵到 boost 库中:http://boost.2283326.n4.nabble.com/boost-interprocess-gt-1-45-robust-mutexes-td3416151.html

The best solution for your problem would be if boost had support for robust mutexes. However Boost currently does not support robust mutexes. There is only a plan to emulate robust mutexes, because only linux has native support on that. The emulation is still just planned by Ion Gaztanaga, the library author. Check this link about a possible hacking of rubust mutexes into the boost libs: http://boost.2283326.n4.nabble.com/boost-interprocess-gt-1-45-robust-mutexes-td3416151.html

与此同时,您可能会尝试在共享段中使用原子变量.

Meanwhile you might try to use atomic variables in a shared segment.

另外看看这个stackoverflow条目:我如何取得废弃的所有权boost::interprocess::interprocess_mutex?

Also take a look at this stackoverflow entry: How do I take ownership of an abandoned boost::interprocess::interprocess_mutex?

当我确实使用超时并且互斥锁被放弃时,ScopedLock ctor 立即返回并告诉我它不拥有互斥锁.好吧,也许这很正常,但为什么它不也等待我告诉它的 10 秒?

When I do use the timeout, and the mutex is abandoned, the ScopedLock ctor returns immediately and tells me that it doesn't own the mutex. Ok, perhaps that's normal, but why isn't it waiting for the 10 seconds I'm telling it too?

这很奇怪,你不应该得到这种行为.然而:定时锁可能是根据尝试锁来实现的.检查此文档:http://www.boost.org/doc/libs/1_53_0/doc/html/boost/interprocess/scoped_lock.html#idp57421760-bb这意味着,定时锁的实现可能会在内部抛出异常,然后返回 false.

This is very strange, you should not get this behavior. However: The timed lock is possibly implemented in terms of the try lock. Check this documentation: http://www.boost.org/doc/libs/1_53_0/doc/html/boost/interprocess/scoped_lock.html#idp57421760-bb This means, the implementation of the timed lock might throw an exception internally and then returns false.

inline bool windows_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
   sync_handles &handles =
      windows_intermodule_singleton<sync_handles>::get();
   //This can throw
   winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
   return mut.timed_lock(abs_time);
}

可能是无法获得句柄,因为互斥量被放弃了.

Possibly, the handle cannot be obtained, because the mutex is abandoned.

当互斥锁没有被放弃并且我使用超时时,ScopedLock构造函数仍然立即返回,告诉我它无法锁定或获取互斥锁的所有权,我完成了删除互斥锁的动作并重新制作它.这根本不是我想要的.

When the mutex isn't abandoned, and I use the timeout, the ScopedLock ctor still returns immediately, telling me that it couldn't lock, or take ownership, of the mutex and I go through the motions of removing the mutex and remaking it. This is not at all what I want.

我不确定这个,但我认为命名互斥锁是通过使用共享内存实现的.如果您使用的是 Linux,请检查文件/dev/shm/MutexName.在 Linux 中,文件描述符在未关闭之前一直有效,无论您是否已通过例如删除文件本身boost::interprocess::named_recursive_mutex::remove.

I am not sure about this one, but I think the named mutex is implemented by using a shared memory. If you are using Linux, check for the file /dev/shm/MutexName. In Linux, a file descriptor remains valid until that is not closed, no matter if you have removed the file itself by e.g. boost::interprocess::named_recursive_mutex::remove.

相关文章