gpt4 book ai didi

c - 在 EOWNERDEAD 状态互斥锁上的 Trylock

转载 作者:行者123 更新时间:2023-12-03 17:22:34 26 4
gpt4 key购买 nike

当我在前任所有者死后尝试使用“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 状态,这是出乎意料的。
状态应该是 ENOTRECOVERABLE 报告 here
我尝试使用“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);
}

最佳答案

我认为您所看到的是,当它返回 EOWNERDEAD 时,锁定互斥锁的尝试被认为是成功的。 (这是恢复语义所必需的,以便只有一个线程尝试恢复)以及当它返回 ENOTRECOVERABLE 时也是如此。 ,我同意这是令人惊讶的,并且似乎与文档相反。文档说,如果线程接收 EOWNERDEAD在解锁之前不会使互斥锁保持一致,然后所有后续尝试锁定它都将返回 ENOTRECOVERABLE .我在文档中没有看到任何内容表明这不应该适用于 pthread_mutex_trylock()pthread_mutex_lock() 相同.
如果您想将其报告为错误,那么您可以针对提供 pthreads 实现的任何库报告它。这至少会因操作系统而异。

in my purpouse i have to check the mutex status before doing any operation, so i cannot use the 'lock' function or a deadlock may occur.


这听起来很可疑。您已经在使用强大的互斥锁,否则您将无法获得 EOWNERDEADENOTRECOVERABLE首先。 pthread_mutex_trylock()可能是矫枉过正,如果不是根本不合适的话。如果在无法锁定互斥锁的情况下可以做有用的工作,则可以使用它。也许在你的情况下有,但那将是不寻常的。例如,如果您只是在再次尝试之前延迟,那么您最好只使用 pthread_mutex_lock()首先。

关于c - 在 EOWNERDEAD 状态互斥锁上的 Trylock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66307312/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com