首先,我知道的互斥体不被认为是异步安全正常。 这个问题涉及使用sigprocmask
使互斥与异步信号和信号处理多线程程序的安全。
我有一些代码在概念上类似如下:
struct { int a, b; } gvars;
void sigfoo_handler(int signo, siginfo_t *info, void *context) {
if(gvars.a == 42 || gvars.b == 13) {
/* run a chained signal handler */
}
}
/* called from normal code */
void update_gvars(int a, int b) {
gvars.a = a;
gvars.b = b;
}
gvars
是一个全局变量太大,适合在一个单一sig_atomic_t
。 它是由正常的代码更新和信号处理程序读取。 受控代码是一个链式信号处理程序,所以它必须在信号处理程序的上下文(其可以使用运行info
或context
)。 因此,所有访问gvars
具有通过某种同步机制来控制。 更加严重的是,该程序是多线程的,任何线程可能会收到一个SIGFOO
。
问:通过结合sigprocmask
(或pthread_sigmask
)和pthread_mutex_t
,是可以保证同步,使用类似于下面的代码?
struct { int a, b; } gvars;
pthread_mutex_t gvars_mutex;
void sigfoo_handler(int signo, siginfo_t *info, void *context) {
/* Assume SIGFOO's handler does not have NODEFER set, i.e. it is automatically blocked upon entry */
pthread_mutex_lock(&gvars_mutex);
int cond = gvars.a == 42 || gvars.b == 13;
pthread_mutex_unlock(&gvars_mutex);
if(cond) {
/* run a chained signal handler */
}
}
/* called from normal code */
void update_gvars(int a, int b) {
sigset_t set, oset;
sigemptyset(&set);
sigaddset(&set, SIGFOO);
pthread_sigmask(SIG_BLOCK, &set, &oset);
pthread_mutex_lock(&gvars_mutex);
gvars.a = a;
gvars.b = b;
pthread_mutex_unlock(&gvars_mutex);
pthread_sigmask(SIG_SETMASK, &oset, NULL);
}
该逻辑是如以下:内sigfoo_handler
, SIGFOO
被阻塞,因此它不能中断pthread_mutex_lock
。 在update_gvars
, SIGFOO
不能在在当前线程提出pthread_sigmask
-保护的关键区域,因此它不能中断pthread_mutex_lock
无论是。 假设没有其他信号(和我们总是能够阻止任何其他信号可能是有问题的),锁定/解锁应该总是在当前线程上的正常的,不间断的方式进行,并利用锁定/解锁的应确保其他线程唐“T干涉。 我说得对,还是应该避免使用此方法?