【问题标题】:Assertion failed on __pthread_mutex_cond_lock_full in a load test负载测试中 __pthread_mutex_cond_lock_full 的断言失败
【发布时间】:2017-04-05 23:15:09
【问题描述】:

我使用以下代码在我在 debian 8 上运行的 c++ 应用程序中创建了一个计时器对象。

class Timer
{
private:
    std::condition_variable cond_;
    std::mutex mutex_;
    int duration;
    void *params;

public:
    Timer::Timer(void (*func)(void*))
    {
      this->handler = func;
      this->duration = 0;
      this->params = NULL;
    };

    Timer::~Timer(){};

    void Timer::start(int duree, void* handlerParams)
    {
      this->duration = duree;
      this->params   = handlerParams;
      /*
       * Launch the timer thread and wait it
       */
      std::thread([this]{
                std::unique_lock<std::mutex> mlock(mutex_);
                std::cv_status ret = cond_.wait_for(mlock, 
                                     std::chrono::seconds(duration));
                if ( ret ==  std::cv_status::timeout )  
                {
                    handler(params);
                }
              }).detach();

      };

      void Timer::stop()
      {
          cond_.notify_all();
      }
    };

它在 gdb 和正常条件下都能正常工作,但在 30 个或更多请求的负载测试中,它会因断言而崩溃:

nptl/pthread_mutex_lock.c:350: __pthread_mutex_cond_lock_full: 断言`(-(e)) != 3 || !robust'失败了。

我不明白这个断言的原因。任何人都可以帮助我吗? 谢谢你

【问题讨论】:

  • 这是 gdb 回溯结果:#0 0xb7fdcd40 in kernel_vsyscall () #1 0xb7621367 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv /linux/raise.c:56 #2 0xb7622a23 in __GI_abort () at abort.c:89 #3 0xb761a6c7 in __assert_fail_base (fmt=0xb7756af4 "%s%s%s:%u: %s%sAssertion `%s' 失败.\n%n", assertion=assertion@entry=0xb7c907f5 "(-(e)) != 3 || !robust",file=file@entry=0xb7c907d8 "../nptl/pthread_mutex_lock.c", line= line@entry=350, function=function@entry=0xb7c90c9c <__pretty_function>.8302> "__pthread_mutex_cond_lock_full") at assert.c:92
  • #4 0xb761a777 in GI___assert_fail (assertion=assertion@entry=0xb7c907f5 "(-(e)) != 3 || !robust", file=file@entry=0xb7c907d8 ".. /nptl/pthread_mutex_lock.c", line=line@entry=350, function=function@entry=0xb7c90c9c <__pretty_function>.8302> "__pthread_mutex_cond_lock_full") at assert.c:101 #5 0xb7c84427 in __pthread_mutex_cond_lock_full (mutex= 0x7ff2e978) at ../nptl/pthread_mutex_lock.c:350 #6 0xb7c8a102 in pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_timedwait。 S:360
  • #6 0xb7c8a102 in pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_timedwait.S:360 #7 /usr/include/i386-linux-gnu/c++/4.9/bits/gthr-default.h:871 #8 __wait_until_impl<:chrono: :duration long std::ratio> > > (__atime=..., __lock=, this=) at /usr/include/c++/4.9/condition_variable: 165
  • 你能提供一个 MCVE stackoverflow.com/help/mcve 吗?

标签: c++ linux pthreads debian mutex


【解决方案1】:

基本上你有一个访问定时器对象的分离线程,所以很可能你销毁了定时器对象但线程仍在运行并访问它的成员(互斥体,条件变量)。

断言本身从 glibc 源代码中说,互斥锁的所有者已经死亡。

【讨论】:

    【解决方案2】:

    非常感谢您的 cmets !我将尝试更改线程分离,并进行负载测试。 这是我的问题的 MVCE,它是大型应用程序的一部分。

    /**
     * \file Timer.hxx
     * \brief Definition of Timer class.
     */
      #include <chrono>
      #include <thread>
      #include <mutex>
      #include <condition_variable>
    
        class Timer
        {
        private:
        std::condition_variable cond_;
        std::mutex mutex_;
        int duration;
        void *params;
    
        public:
        Timer(void (*func)(void*));
        ~Timer();
    
        void (*handler)(void*);
        void start(int duree, void* handlerParams);
        void stop();
        };
    
     /*
     * Timer.cxx
     */
     #include "Timer.hxx"
     Timer::Timer(void (*func)(void*))
    {
    //this->set_handler(func, params);
    this->handler = func;
    this->duration = 0;
    this->params = NULL;
    }
    
    Timer::~Timer()
    {
    }
    
    void Timer::start(int duree, void* handlerParams)
    {
    this->duration = duree;
    this->params   = handlerParams;
    /*
     * Launch the timer thread and wait it
     */
    std::thread([this]{
                    std::unique_lock<std::mutex> mlock(mutex_);
                    std::cv_status ret = cond_.wait_for(mlock, std::chrono::seconds(duration));
                    if ( ret ==  std::cv_status::timeout )  
                    {
                        handler(params);
                    }
                  }).detach();
    
       }
    
    
     void Timer::stop()
     {
      cond_.notify_all();
     }
    
    /*
     * MAIN
     */
    #include <stdio.h>
    #include <iostream>
    #include <unistd.h>
    #include "Timer.hxx"
    
    using namespace std;
    
    void timeoutHandler(void* params)
    {
    char* data= (char*)params;
    cout << "Timeout triggered !! Received data is: " ;
    if (data!=NULL)
        cout << data << endl;   
    }
    
    int main(int argc, char **argv)
    {
    int delay=5;
    char data[20] ="This is a test" ;
    
    Timer *t= new Timer(&timeoutHandler) ;
    t->start(delay, data);
    cout << "Timer started !! " << endl;    
    sleep(1000);
    t->stop();
    delete t;
    cout << "Timer deleted !! " << endl;    
    
    return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-29
      • 2017-04-10
      • 2020-10-08
      • 1970-01-01
      • 1970-01-01
      • 2019-12-27
      • 2017-10-31
      • 2020-08-06
      相关资源
      最近更新 更多