EOWNERDEAD状态互斥体上的Trylock

EOWNERDEAD状态互斥体上的Trylock,c,pthreads,mutex,C,Pthreads,Mutex,当前一个所有者死后,我试图用“trylock”锁定互斥锁时,发现了意外行为 没有解锁它。 第一个使用“trylock”的进程按预期获取EOWNERDEAD状态,因此使用“unlock”函数来释放互斥: lock_status = pthread_mutex_trylock(mutex); if (lock_status == EOWNERDEAD) { pthread_mutex_unlock(mutex); printf("P1 mutex status: EOWNE

当前一个所有者死后,我试图用“trylock”锁定互斥锁时,发现了意外行为 没有解锁它。
第一个使用“trylock”的进程按预期获取EOWNERDEAD状态,因此使用“unlock”函数来释放互斥:

lock_status = pthread_mutex_trylock(mutex);
if (lock_status == EOWNERDEAD)
{
    pthread_mutex_unlock(mutex);
    printf("P1 mutex status: EOWNERDEAD\n");
}
else if (lock_status == ENOTRECOVERABLE)
    {printf("P1 mutex status: ENOTRECOVERABLE\n");}
else if (lock_status == EBUSY)
    {printf("P1 mutex status: EBUSY\n");}
else {printf("P1 mutex status: %d\n", lock_status);}
第二个执行与预期相同的代码,以获得ENOTRECOVERABLE状态。
但是当第三个执行相同的操作时,会得到EBUSY状态,这是意外的。
报告的状态应不可覆盖
我尝试使用“lock”函数代替“trylock”,并返回了正确的状态。
那是虫子吗?出于我的目的,我必须在执行任何操作之前检查互斥锁状态,因此我不能使用“锁定”功能,否则可能会发生死锁。
我正在考虑在ENOTRECOVERABLE状态返回时销毁互斥锁:

else if (lock_status == ENOTRECOVERABLE)
{
    pthread_mutex_destroy(mutex);
    printf("P1 mutex status: ENOTRECOVERABLE\n");
}
但也许有一个更好的方法比这个激烈的解决方案,是吗? 完整代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

main(void)
{
int lock_status, mutex_fdesc;
pid_t process_id;
pthread_mutex_t* mutex;
pthread_mutexattr_t m_att;

//Process 1 die with locked mutex
process_id = fork();
if (process_id < 0) {exit(0);}
if (process_id == 0)
{
    usleep(100000);
    mutex_fdesc = shm_open("/mutex", O_RDWR, S_IRWXU | S_IRWXG);
    mutex = (pthread_mutex_t*)mmap(NULL, sizeof(pthread_mutex_t), 
                PROT_READ | PROT_WRITE, MAP_SHARED, mutex_fdesc, 0);
    close(mutex_fdesc);
    pthread_mutex_lock(mutex);
    exit(0);
}
///Process 2 try to lock mutex and gets EOWNERDEAD then make an unlock
process_id = fork();
if (process_id < 0) {exit(0);}
if (process_id == 0)
{
    usleep(200000);
    mutex_fdesc = shm_open("/mutex", O_RDWR, S_IRWXU | S_IRWXG);
    mutex = (pthread_mutex_t*)mmap(NULL, sizeof(pthread_mutex_t), 
                PROT_READ | PROT_WRITE, MAP_SHARED, mutex_fdesc, 0);
    close(mutex_fdesc);
    lock_status = pthread_mutex_trylock(mutex);
    if (lock_status == EOWNERDEAD)
        {
        pthread_mutex_unlock(mutex);
        printf("P2 mutex status: EOWNERDEAD\n");}
    else if (lock_status == ENOTRECOVERABLE)
        {printf("P2 mutex status: ENOTRECOVERABLE\n");}
    else if (lock_status == EBUSY)
        {printf("P2 mutex status: EBUSY\n");}
    else {printf("P2 mutex status: %d\n", lock_status);}
    exit(0);
}
///Process 2 try to lock mutex and gets ENOTRECOVERABLE then do nothing
process_id = fork();
if (process_id < 0) {exit(0);}
if (process_id == 0)
{
    usleep(400000);
    mutex_fdesc = shm_open("/mutex", O_RDWR, S_IRWXU | S_IRWXG);
    mutex = (pthread_mutex_t*)mmap(NULL, sizeof(pthread_mutex_t), 
                PROT_READ | PROT_WRITE, MAP_SHARED, mutex_fdesc, 0);
    close(mutex_fdesc);
    lock_status = pthread_mutex_trylock(mutex);
    if (lock_status == EOWNERDEAD)
        {
        pthread_mutex_unlock(mutex);
        printf("P3 mutex status: EOWNERDEAD\n");}
    else if (lock_status == ENOTRECOVERABLE)
        {printf("P3 mutex status: ENOTRECOVERABLE\n");}
    else if (lock_status == EBUSY)
        {printf("P3 mutex status: EBUSY\n");}
    else {printf("P3 mutex status: %d\n", lock_status);}
    exit(0);
}

mutex_fdesc = shm_open("/mutex", O_RDWR | O_CREAT | O_EXCL, S_IRWXU | S_IRWXG);
ftruncate(mutex_fdesc, sizeof(pthread_mutex_t));
mutex = (pthread_mutex_t*)mmap(NULL, sizeof(pthread_mutex_t), 
            PROT_READ | PROT_WRITE, MAP_SHARED, mutex_fdesc, 0);
close(mutex_fdesc);
pthread_mutexattr_init(&m_att);
pthread_mutexattr_setpshared(&m_att, PTHREAD_PROCESS_SHARED);
pthread_mutexattr_setrobust(&m_att, PTHREAD_MUTEX_ROBUST);
pthread_mutex_init(mutex, &m_att);
pthread_mutexattr_destroy(&m_att);
///Parent process try to lock the mutex and gets EBUSY
usleep(800000);
lock_status = pthread_mutex_trylock(mutex);
if (lock_status == EOWNERDEAD)
        {printf("Pparent mutex status: EOWNERDEAD\n");}
    else if (lock_status == ENOTRECOVERABLE)
        {printf("Pparent mutex status: ENOTRECOVERABLE\n");}
    else if (lock_status == EBUSY)
        {printf("Pparent mutex status: EBUSY\n");}
    else {printf("Pparent mutex status: %d\n", lock_status);}

pthread_mutex_destroy(mutex);
munmap((void*)mutex, sizeof(pthread_mutex_t));
shm_unlink("/mutex");
wait(NULL);
wait(NULL);
wait(NULL);
exit(0);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
主(空)
{
int lock_状态、互斥体_fdesc;
进程id;
pthread_mutex_t*mutex;
pthread_mutextatr_t m_att;
//进程1带锁定互斥锁的模具
进程_id=fork();
if(进程id<0){exit(0);}
如果(进程id==0)
{
美国LEEP(100000);
mutex_fdesc=shm_open(“/mutex”,O_RDWR,S_IRWXU | S_IRWXG);
互斥=(pthread\u mutex\u t*)mmap(NULL,sizeof(pthread\u mutex\u t),
保护读取、保护写入、映射共享、互斥、0);
关闭(互斥锁);
pthread_mutex_lock(互斥锁);
出口(0);
}
///进程2尝试锁定互斥锁并获取EOWNERDEAD,然后进行解锁
进程_id=fork();
if(进程id<0){exit(0);}
如果(进程id==0)
{
usleep(200000);
mutex_fdesc=shm_open(“/mutex”,O_RDWR,S_IRWXU | S_IRWXG);
互斥=(pthread\u mutex\u t*)mmap(NULL,sizeof(pthread\u mutex\u t),
保护读取、保护写入、映射共享、互斥、0);
关闭(互斥锁);
lock\u status=pthread\u mutex\u trylock(互斥锁);
如果(锁定状态==EOWnerDed)
{
pthread_mutex_unlock(互斥锁);
printf(“P2互斥体状态:eownerded\n”);}
else if(锁定状态==ENOTREOVERABLE)
{printf(“P2互斥状态:ENOTRECOVERABLE\n”);}
else if(锁定状态==EBUSY)
{printf(“P2互斥状态:EBUSY\n”);}
else{printf(“P2互斥状态:%d\n”,锁定状态);}
出口(0);
}
///进程2尝试锁定互斥锁,并获得ENOTRECOVERABLE,然后什么也不做
进程_id=fork();
if(进程id<0){exit(0);}
如果(进程id==0)
{
美国利普(400000);
mutex_fdesc=shm_open(“/mutex”,O_RDWR,S_IRWXU | S_IRWXG);
互斥=(pthread\u mutex\u t*)mmap(NULL,sizeof(pthread\u mutex\u t),
保护读取、保护写入、映射共享、互斥、0);
关闭(互斥锁);
lock\u status=pthread\u mutex\u trylock(互斥锁);
如果(锁定状态==EOWnerDed)
{
pthread_mutex_unlock(互斥锁);
printf(“P3互斥体状态:EOWNERDEAD\n”);}
else if(锁定状态==ENOTREOVERABLE)
{printf(“P3互斥状态:ENOTRECOVERABLE\n”);}
else if(锁定状态==EBUSY)
{printf(“P3互斥状态:EBUSY\n”);}
else{printf(“P3互斥体状态:%d\n”,锁状态);}
出口(0);
}
mutex_fdesc=shm_open(“/mutex”,O|RDWR | O|u CREAT | O|u EXCL,S|IRWXU | S|IRWXG);
ftruncate(mutex_fdesc,sizeof(pthread_mutex_t));
互斥=(pthread\u mutex\u t*)mmap(NULL,sizeof(pthread\u mutex\u t),
保护读取、保护写入、映射共享、互斥、0);
关闭(互斥锁);
pthread_mutexattr_init(&m_att);
pthread_mutexattr_setpshared(&m_att,pthread_PROCESS_SHARED);
pthread_mutexattr_setrobust(&m_att,pthread_MUTEX_ROBUST);
pthread_mutex_init(mutex和m_att);
pthread_mutexattr_destroy(&m_att);
///父进程尝试锁定互斥锁并获取EBUSY
美国LEEP(800000);
lock\u status=pthread\u mutex\u trylock(互斥锁);
如果(锁定状态==EOWnerDed)
{printf(“Pparent互斥体状态:EOWNERDEAD\n”);}
else if(锁定状态==ENOTREOVERABLE)
{printf(“Pparent互斥体状态:ENOTRECOVERABLE\n”);}
else if(锁定状态==EBUSY)
{printf(“Pparent互斥体状态:EBUSY\n”);}
else{printf(“Pparent互斥体状态:%d\n”,锁状态);}
pthread_mutex_destroy(互斥);
munmap((void*)互斥体,sizeof(pthread_mutex_t));
shm_取消链接(“/mutex”);
等待(空);
等待(空);
等待(空);
出口(0);
}

我认为您看到的是,当它返回
EOWNERDEAD
(这是恢复语义所必需的,因此只有一个线程尝试恢复)以及当它返回
ENOTRECOVERABLE
时,锁定互斥锁的尝试被认为是成功的,我同意这是令人惊讶的,而且似乎与文件相反。文档说,如果接收
EOWNERDEAD
的线程在解锁之前没有使互斥锁保持一致,那么所有后续锁定互斥锁的尝试都将返回
ENOTRECOVERABLE
。我在文档中看不到任何东西表明这不应该适用于
pthread\u mutex\u trylock()
,就像它适用于
pthread\u mutex\u lock()
一样

如果您想将其报告为bug,那么您可以针对提供pthreads实现的任何库报告它。这至少会因操作系统而异

出于我的目的,我必须在执行任何操作之前检查互斥状态,因此我不能使用“锁定”功能,否则可能会发生死锁


听起来很可疑。您已经在使用健壮的互斥锁,否则您首先将无法获得
EOWNERDEAD
ENOTRECOVERABLE
pthread\u mutex\u trylock()
如果不是不合适的话,可能是杀伤力过大。如果在无法锁定互斥锁的情况下可以做一些有用的工作,则可以使用它。也许在你的情况下有,但那是不寻常的。例如,如果在重试之前只是延迟,那么最好首先使用
pthread\u mutex\u lock()

为什么不存储原始所有者在正常状态下死亡的信息呢