【发布时间】:2013-12-24 17:16:08
【问题描述】:
我有一个进程共享的 pthread 条件(带有关联的互斥锁)。如果在这种情况下等待的进程(使用 pthread_cond_wait() 或 pthread_cond_timedwait())被终止会发生什么?这个条件还能被其他进程使用吗?
在我的场景中,进程#1 等待条件并被终止。进程 #2 在某些时候发现它是现在唯一使用该条件的进程并调用 pthread_cond_destroy()。
我看到的是 pthread_cond_destroy() 只是挂起。有没有人遇到过同样的问题?
从 pthread_cond_destroy() 的手册页中可以看出,破坏某些线程仍在等待的条件会导致未定义的行为。在我的情况下,当进程 #2 调用 pthread_cond_destroy() 时,没有人在等待,因为等待进程 #1 已终止,但显然条件本身仍然认为有一个等待线程。
有没有办法解决这个问题?
编辑:
根据要求,我发布示例程序(我在这里颠倒了 p1 和 p2):
p1.cpp:
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
struct MyCond {
pthread_mutex_t m;
pthread_cond_t c;
};
int main()
{
pthread_mutexattr_t ma;
pthread_mutexattr_init(&ma);
pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
pthread_condattr_t ca;
pthread_condattr_init(&ca);
pthread_condattr_setpshared(&ca, PTHREAD_PROCESS_SHARED);
int fd = shm_open("/test_cond_p", O_RDWR|O_CREAT, 0666);
ftruncate(fd, sizeof(MyCond));
MyCond *c = (MyCond *)mmap(NULL, sizeof(MyCond),
PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);
//close (fd);
pthread_mutex_init(&c->m, &ma);
pthread_cond_init(&c->c, &ca);
printf("Inited MyCond, %x\n", c);
puts("Press Enter to continue");
fgetc(stdin);
int r = pthread_cond_signal(&c->c);
printf("After pthread_cond_signal, r=%d\n", r);
puts("Before pthread_cond_destroy");
r = pthread_cond_destroy(&c->c);
printf("After pthread_cond_destroy, r=%d\n", r);
r = pthread_mutex_destroy(&c->m);
printf("After pthread_mutex_destroy, r=%d\n", r);
munmap(c, sizeof(MyCond));
shm_unlink("/test_cond_p");
return 0;
}
p2.cpp:
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
struct MyCond {
pthread_mutex_t m;
pthread_cond_t c;
};
int main()
{
int fd = shm_open("/test_cond_p", O_RDWR, 0666);
MyCond *c = (MyCond *)mmap(NULL, sizeof(MyCond),
PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);
//close (fd);
pthread_mutex_lock(&c->m);
puts("Before pthread_cond_wait");
int r = pthread_cond_wait(&c->c, &c->m);
printf("After pthread_cond_wait, r=%d\n", r);
munmap(c, sizeof(MyCond));
return 0;
}
先运行p1,然后运行p2,在它说“在pthread_cond_wait之前”之后,Ctrl-C它。然后在 p1 的 shell 中按 Enter。
起初,我无法重现挂起,但我让 pthread_cond_destroy() 和 pthread_mutex_destroy() 返回 EBUSY。
但是现在如果我们在 pthread_cond_destroy() 之前调用 pthread_cond_signal() 就会重现挂起(参见上面的代码)。
【问题讨论】:
-
“被终止”是否意味着调用了 pthread_cancel?在这种情况下,您应该启用清理处理程序。这是使用互斥锁的用户定义的 rwlock 对象的 POSIX 示例。请参阅示例部分:pubs.opengroup.org/onlinepubs/009695299/functions/…
-
请显示一些代码。
-
致吉姆:不,我的意思是当整个过程通过信号终止时,我们假设没有办法拦截该信号来进行任何清理。
-
致 Pilcrow:代码中还有很多其他不相关的事情,所以整个代码很难在这里发布,但为了澄清场景:进程 #2 创建共享内存段来存储条件及其关联的互斥体并在它们上调用 pthread_cond_init() 和 pthread_mutex_init() (启用 pthread_process_shared 属性)。然后它继续运行做其他事情。进程#1 映射到所述共享内存段,获取指向条件和互斥变量的指针。然后它获取互斥体并调用 pthread_cond_wait() 等待条件。
-
您是否建议永远不要调用 pthread_cond_destroy 和 pthread_mutex_destroy?我不会泄漏内存或其他资源吗?
标签: c multithreading unix pthreads ipc