我们正在使用pthread_mutex_t来保护不同进程访问的共享内存。
在最近更新glibc(https://sourceware.org/ml/libc-alpha/2017-02/msg00079.html)之后,代码确实停止工作,导致每个涉及的进程陷入僵局。
将事情置于上下文中:代码运行多年,最近从未遇到过任何问题。代码库没有变化,降级glibc“解决”了这个问题。
方案如下: 一个进程创建并托管共享内存,其他进程连接到受pthread_mutex_t保护的同一共享内存。使用以下命令创建互斥锁:
int err;
pthread_mutexattr_t mattr;
err=pthread_mutexattr_init(&mattr);
if( err != 0 )
DIE("initializing mutex attributes failed: %s",strerror(err));
err=pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK);
if( err != 0 )
ERR("setting mutex attribute ERRORCHECK failed: %s",strerror(err));
err=pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST);
if( err != 0 )
ERR("setting mutex attribute PTHREAD_MUTEX_ROBUST failed: %s",strerror(err));
err=pthread_mutexattr_setpshared(&mattr,PTHREAD_PROCESS_SHARED);
if( err != 0 )
ERR("setting mutex attribute PROCESS_SHARED failed: %s",strerror(err));
err=pthread_mutex_init(mutex,&mattr);
if( err != 0 )
DIE("initializing mutex failed: %s",strerror(err));
并以
锁定pthread_mutex_lock(mutex);
只要每个进程仅从其一个线程访问共享内存,一切都按预期工作。一旦任何进程有另一个线程访问互斥锁,一段时间后一切都会死锁。
mutex->__data.__owner
的值始终与第一种情况(当前持有互斥锁的线程的线程ID)一样。
在第二种情况下,只要进程A的线程2想要锁定互斥锁,而进程A的线程1具有当前锁定的互斥锁,'mutex-> __ data .__ owner`最终会出现一些负面的乱码并且任何线程都无法解锁互斥锁。
互斥体损坏恰好发生在第二次锁定的时刻,而不是由于其他一些内存损坏错误(使用valgrind和硬件gdb检查)。
如果锁定互斥锁的代码切换为
int success = 1;
while ( success != 0 )
{
err=pthread_mutex_trylock(mutex);
success = err;
}
一切正常,没有发生僵局。
任何人都可以从这个简短的场景中说出可能存在错误吗?