boost::mutex,pthread_mutex_destroy 失败 - 调试建议?

发布于 2024-11-30 19:14:08 字数 2446 浏览 0 评论 0原文

我们在静态类中有几个锁(boost::mutex),但是当程序退出时,pthread_mutex_destroy在互斥体的析构函数中失败(boost中有一个断言检查这一点)。

据我所知,pthread_mutex_destroy只会在两种情况下失败。

[EBUSY]  The implementation has detected an attempt to destroy the object referenced by mutex   while it is locked or referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread.
[EINVAL] The value specified by mutex is invalid.

当我在 GDB 中运行并打印锁时,我看到它已解锁。 不幸的是我在 GDB 中打印 errno 时遇到问题。

#3  0x000000000044a2c6 in ~mutex (this=0x847840, __in_chrg=<value optimized out>) at /usr/include/boost/thread/pthread/mutex.hpp:47
47              BOOST_VERIFY(!pthread_mutex_destroy(&m));
(gdb) p m
$1 = {__data = {__lock = 0, __count = 0, __owner = 0, __nusers = 4294967294, __kind = 0, __spins = 0, __list = {__prev = 0x0, 
      __next = 0x0}}, __size = '\000' <repeats 12 times>"\376, \377\377\377", '\000' <repeats 23 times>, __align = 0}

现在我正在写这篇文章,__nusers 和 __size 的值看起来很奇怪。这可能暗示锁无效,但我知道锁在某些时候是有效的(我将 boost::mutex 包装在 Lock 类中,在构造函数、析构函数和锁中打印了 this(0x847840) 的值/解锁功能。

任何有关如何调试的帮助将不胜感激

。 Locks 类继承自 boost::mutex,并导出作用域锁(从内存):

lock_type::scoped_lock getScopedLock() {
  return lock_type::scoped_lock( *this );
}

我还尝试将锁添加为成员,而不是继承它,行为没有任何变化。 我不认为 getScopedLock 函数会引入任何问题(作用域锁返回 y 值,但由于 RVO 而没有创建副本),但认为它值得一提。 它的使用如下(我们使用的是c++0x):

auto lock = lock_.getScopedLock();

完整的stracktrace:

(gdb) where
#0  0x00007ffff559da75 in *__GI_raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1  0x00007ffff55a15c0 in *__GI_abort () at abort.c:92
#2  0x00007ffff5596941 in *__GI___assert_fail (assertion=0x55851c "!pthread_mutex_destroy(&m)", file=<value optimized out>, line=47, 
    function=0x5595a0 "boost::mutex::~mutex()") at assert.c:81
#3  0x000000000044a2c6 in ~mutex (this=0x847840, __in_chrg=<value optimized out>) at /usr/include/boost/thread/pthread/mutex.hpp:47
#4  0x000000000044d923 in ~Lock (this=0x847840, __in_chrg=<value optimized out>) at include/Locks.h:43
#5  0x00007ffff55a3262 in __run_exit_handlers (status=0) at exit.c:78
#6  *__GI_exit (status=0) at exit.c:100
#7  0x00000000004ea9a6 in start () at src/main.cc:191
#8  0x00000000004de5aa in main (argc=1, argv=0x7fffffffe7b8) at src/main.cc:90

We have several locks (boost::mutex) in static classes, but when the program exits, pthread_mutex_destroy fails in the destructor of the mutex (there is an assertion checking this in boost).

As far as I know, pthread_mutex_destroy will only fail in two cases.

[EBUSY]  The implementation has detected an attempt to destroy the object referenced by mutex   while it is locked or referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread.
[EINVAL] The value specified by mutex is invalid.

When I run in GDB and I print the lock I see that it is unlocked.
Unfortunately I'm having trouble printing errno in GDB.

#3  0x000000000044a2c6 in ~mutex (this=0x847840, __in_chrg=<value optimized out>) at /usr/include/boost/thread/pthread/mutex.hpp:47
47              BOOST_VERIFY(!pthread_mutex_destroy(&m));
(gdb) p m
$1 = {__data = {__lock = 0, __count = 0, __owner = 0, __nusers = 4294967294, __kind = 0, __spins = 0, __list = {__prev = 0x0, 
      __next = 0x0}}, __size = '\000' <repeats 12 times>"\376, \377\377\377", '\000' <repeats 23 times>, __align = 0}

Now that I am writing this post the value of __nusers and __size look strange. This could hint to the lock being invalid, but I know that the lock was valid at some point (I wrap the boost::mutex in a Lock class, where I printed the value of this(0x847840) in the constructor, destructor and lock/unlock functions.

Any help as to how to debug this would be greatly appreciated.

Edit
The Locks class inherits from boost::mutex, and exports a scopedlock (from memory):

lock_type::scoped_lock getScopedLock() {
  return lock_type::scoped_lock( *this );
}

I've also tried to add the lock as a member, instead of inheriting from it, with no change in behavior.
I do not think that the getScopedLock function could introduce any problems(the scoped lock is returned y value, but a copy is not made because of RVO), but thought it could be worth mentioning.
It is used as follows (we are using c++0x):

auto lock = lock_.getScopedLock();

The complete stracktrace:

(gdb) where
#0  0x00007ffff559da75 in *__GI_raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1  0x00007ffff55a15c0 in *__GI_abort () at abort.c:92
#2  0x00007ffff5596941 in *__GI___assert_fail (assertion=0x55851c "!pthread_mutex_destroy(&m)", file=<value optimized out>, line=47, 
    function=0x5595a0 "boost::mutex::~mutex()") at assert.c:81
#3  0x000000000044a2c6 in ~mutex (this=0x847840, __in_chrg=<value optimized out>) at /usr/include/boost/thread/pthread/mutex.hpp:47
#4  0x000000000044d923 in ~Lock (this=0x847840, __in_chrg=<value optimized out>) at include/Locks.h:43
#5  0x00007ffff55a3262 in __run_exit_handlers (status=0) at exit.c:78
#6  *__GI_exit (status=0) at exit.c:100
#7  0x00000000004ea9a6 in start () at src/main.cc:191
#8  0x00000000004de5aa in main (argc=1, argv=0x7fffffffe7b8) at src/main.cc:90

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风为裳 2024-12-07 19:14:08

当您在没有先锁定互斥体的情况下解锁互斥体时,通常会出现此错误。

  boost::mutex m;
  m.unlock();

我的猜测是,您在某个地方使用 lockunlock 成员而不是 RAII
并且您丢失了对 lock 的调用。

请注意,大多数时候您不应该调用 lockunlock 成员。使用 scoped_lock 来为您调用函数。

struct s
{
  void foo()
  {
    boost::mutex::scoped_lock l(m_mutex);
    //do something
  }
  private: 
    boost::mutex m_mutex;
};

另外,您提到您是从 boost::mutex 继承的。这可能会导致问题,因为 boost::mutex 没有虚拟析构函数,因此最好不要这样做。

You typically get this error when you unlock your mutex without locking it first.

  boost::mutex m;
  m.unlock();

My guess is that somewhere you are using lock and unlock members rather than RAII,
and that you have lost a call to lock.

Note that most of the time you should not be calling the lock and unlock members. Use the scoped_lock which calls the functions for you.

struct s
{
  void foo()
  {
    boost::mutex::scoped_lock l(m_mutex);
    //do something
  }
  private: 
    boost::mutex m_mutex;
};

Also, you mention that you are inheriting from boost::mutex. This can cause problems becuase boost::mutex does not have a virtual destructor, so its best not to do that.

黒涩兲箜 2024-12-07 19:14:08

好吧,结果有两个问题。
有一把锁,从来没有被使用过,但是当我停下来时,我确实调用了解锁。
显然我没有正确阅读文档,因为解锁有一个前提条件,即当前线程必须拥有锁。
谢谢汤姆让我看到这个。

第二个问题是,我在某个地方有一个作用域锁,我想在它超出作用域之前解锁它:

auto lock = lock_.getScopedLock();
if( something )
   lock.unlock();

最初,这读作 lock_.unlock();,所以我正在解锁互斥体,不通过作用域锁。

@Tom,我不喜欢写 boost::mutex::scoped_lock l(lock_) 的原因是如果你写 boost::mutex::scoped_lock l() > 不会有任何错误。
现在,我看到的唯一危险是有人编写 lock_.getScopedLock() 而不将其存储在变量中,我想当其他人开始接触代码时,我们只需定义一个宏来获取作用域锁(是的,我们可以对没有 getScopedLock 的变体执行相同的操作;))。
无论如何,我不再从 boost::mutex 继承,而是将其保留为成员。你是对的,我们不应该冒险继承它。

@丹尼尔,
使用 -lpthread 编译没有帮助,我现在没有时间查看该特定问题,因为我不需要它,但无论如何还是感谢您的建议。

@萨姆,
我确实在 valgrind 中运行,但它没有显示锁定问题的有趣输出。

Ok turns out there were two problems.
There was one lock, which never got used but when stopping I did call unlock.
Obviously I didn't read the documentation correctly, as there is a precondition on unlock that the current thread must own lock.
Thank you Tom for getting me to see this.

The second problem was that somewhere I have a scoped lock, and I want to unlock it before it goes out of scope:

auto lock = lock_.getScopedLock();
if( something )
   lock.unlock();

Originally, this read lock_.unlock();, so I was unlocking the mutex, not via the scoped lock.

@Tom, the reason I don't like writing boost::mutex::scoped_lock l(lock_) is that if you write boost::mutex::scoped_lock l() there will be no errors whatsoever.
Now, the only danger I see is that someone writes lock_.getScopedLock() without storing it in a variable, I guess when someone else starts touching the code we'd just define a macro for getting the scoped lock (yes yes, we could do the same for the variant without getScopedLock ;)).
In any case, I'm not inheriting from boost::mutex anymore, but instead keeping it as a member. You are right that we should not risk inheriting from it.

@Daniel,
Compiling with -lpthread did not help, I don't have time to look at that particular problem at the moment, as I don't need it, but thank you for your suggestion anyway.

@Sam,
I did run in valgrind, but it showed no interesting output to the lock problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文