2011-08-23 3 views
1

정적 클래스에는 몇 가지 잠금 (boost :: mutex)이 있지만 프로그램이 종료되면 pthread_mutex_destroy가 뮤텍스의 소멸자에서 실패합니다 (부스트에서이를 확인하는 어설 션이 있음).boost :: mutex, pthread_mutex_destroy failed - 디버깅 제안 사항?

내가 아는 한, 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 값이 이상하게 보입니다. 이것은 잠금 장치가 유효하지 않음을 암시 할 수 있지만 잠금이 유효하다는 것을 알고 있습니다. (Lock 클래스의 boost :: mutex를 래핑합니다.이 클래스의 값은 생성자, 소멸자 및 잠금에 0x847840으로 표시됩니다./기능의 잠금을 해제

어떤 도움을이 크게 감상 할 수 디버깅하는 방법에 관한

편집 잠금 클래스는 부스트 :: 뮤텍스를 상속하고 (메모리)를 scopedlock를 보냅니다..

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

나는 또한 상속 대신 멤버로 잠금을 추가하려고했습니다. 그것은 행동 변화가없는 것입니다. getScopedLock 함수가 문제를 일으킬 수 있다고 생각하지 않습니다 (범위가 지정된 잠금은 y 값이 반환되지만 RVO로 인해 복사본이 만들어지지 않음).하지만 언급 할만한 가치가 있다고 생각했습니다. (우리가 + +0을 C를 사용) 다음과 같이 사용됩니다 :

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 
+0

코드를 보여 주면 도움이 될 것입니다 (예 :'Locks.h'에서 무슨 일이 일어나는지) – Tom

+1

글을 올릴 수있는 코드가 거의 없습니다.이 글을 올린 이유 중 하나는 모르겠습니다. 문제를 찾기 위해 수천 줄의 코드가 필요합니다. 그래서 불행히도 나는 작은 테스트 케이스를 만들 수 없다. 나는 여러 잠금 중 어떤 것이 깨지는 지 알지 못한다. (나는 그것들을 초기화하는 모든 잠금의 주소를 출력함으로써 알아낼 수있다.) 잠금 클래스는 boost :: mutex atm으로부터 상속 받는다. 다른 사람. – thelamb

+0

@thelamb 재생기를 게시 할 수없는 경우 valgrind에서 코드를 실행하십시오. –

답변

3

당신은 일반적으로이 오류를 얻을 때 먼저 잠금없이 당신 unlock 뮤텍스.

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에는 가상 소멸자가 없으므로 문제가 발생할 수 있으므로 그렇게하지 않는 것이 좋습니다.

+0

답장을 보내 주셔서 감사합니다. 자물쇠 및 ulock 사용 여부를 확인하겠습니다. 대부분의 경우 scoped_lock을 이미 사용하고 있습니다. 상속에 대한 귀하의 권리는 안전하지 않지만 Lock을 수정하여 멤버로 뮤텍스를 유지하고 문제가 지속되는 잠금/잠금 해제 함수를 내보내는 경우 이미 확인했습니다. 이 작업을 다시 수행하고 잠금 해제가 먼저 호출되고 상태가 아직 잠금 해제되어 있는지 확인하기 위해 변수를 유지합니다. Lock에 관한 한 가지 언급을 잊어 버렸습니다. 내 편집 된 게시물 – thelamb

+0

을 getScopedLock에 대한 우려로 보았습니다. C++ 0x를 사용하고 있음을 언급해야합니다. 스코프 잠금 장치는 움직일 수 있습니다. 그러나 이동이나 복사가 여기에 관련되어 있지 않기 때문에 아무런 문제가 없어야합니다 (다른 컴파일러에서 작동하지 않는 것에 너무 신경 쓰지 않습니다). – thelamb

3

두 가지 문제가 있습니다. 사용하지 않은 잠금 장치가 하나 있었지만 멈출 때 잠금 해제를 호출했습니다. 분명히 설명서를 올바르게 읽지 못했습니다. 잠금 해제에 대한 전제 조건은 현재 스레드가 자신의 잠금을 소유해야한다는 것입니다. Tom이 나를 보게 해주셔서 감사합니다.

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

를 원래이 lock_.unlock();을 읽고, 그래서 나는, 뮤텍스를 잠금 해제되지 않은 :이 범위를 벗어나 전에

두 번째 문제는 어딘가에는 범위의 잠금을 가지고 있고, 내가 잠금을 해제하려는 것이 었습니다 범위가 지정된 잠금 장치를 통해

@ 톰, 내가 쓰는 것을 좋아하지 않는 이유는 boost::mutex::scoped_lock l(lock_)입니다. boost::mutex::scoped_lock l()을 쓰면 오류가 전혀 발생하지 않습니다. 이제 볼 수있는 유일한 위험은 다른 사람이 변수에 저장하지 않고 lock_.getScopedLock()을 쓰지 않는다는 것입니다. 누군가 다른 사람이 코드를 만지기 시작하면 우리는 스코프 된 잠금을 얻기 위해 매크로를 정의 할 것입니다 (예, 그렇습니다. getScopedLock이없는 변형의 경우))). 어쨌든, 나는 더 이상 boost::mutex에서 상속하지 않고 대신 회원으로 유지합니다. 당신은 우리가 그것을 상속받을 위험이 없어야한다고 옳습니다.

@ Daniel, -lpthread를 사용하여 컴파일하는 것이 도움이되지 않았지만 필자는이 특정 문제를 볼 필요가 없으므로 시간이 없습니다. 어쨌든 당신의 제안에 감사드립니다.

@Sam, valgrind에서 실행했지만 잠금 문제에 대한 흥미로운 결과가 표시되지 않았습니다.

관련 문제