我是新的信号量,并希望添加多线程到我的程序,但我无法解决以下问题:sem_wait()应该能够接收EINTR和解锁,只要我didn不设置SA_RESTART标志。我发送一个SIGUSR1给在sem_wait()中被阻塞的工作者线程,它接收到信号并被中断,但是它将继续阻塞,所以它永远不会给我一个-1返回码和errno = EINTR 。但是,如果我从主线程执行sem_post,它会解除阻塞,给我一个EINTR的错误,但是RC为0.我对这种行为感到十分困惑。这是一些奇怪的NetBSD实现还是我在这里做错了什么?根据手册页,sem_wait符合POSIX.1(ISO/IEC 9945-1:1996)。一个简单的代码:sem_wait不解锁与EINTR
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
typedef struct workQueue_s
{
int full;
int empty;
sem_t work;
int sock_c[10];
} workQueue_t;
void signal_handler(int sig)
{
switch(sig)
{
case SIGUSR1:
printf("Signal: I am pthread %p\n", pthread_self());
break;
}
}
extern int errno;
workQueue_t queue;
pthread_t workerbees[8];
void *BeeWork(void *t)
{
int RC;
pthread_t tid;
struct sigaction sa;
sa.sa_handler = signal_handler;
sigaction(SIGUSR1, &sa, NULL);
printf("Bee: I am pthread %p\n", pthread_self());
RC = sem_wait(&queue.work);
printf("Bee: got RC = %d and errno = %d\n", RC, errno);
RC = sem_wait(&queue.work);
printf("Bee: got RC = %d and errno = %d\n", RC, errno);
pthread_exit((void *) t);
}
int main()
{
int RC;
long tid = 0;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
queue.full = 0;
queue.empty = 0;
sem_init(&queue.work, 0, 0);
printf("I am pthread %p\n", pthread_self());
pthread_create(&workerbees[tid], &attr, BeeWork, (void *) tid);
pthread_attr_destroy(&attr);
sleep(2);
sem_post(&queue.work);
sleep(2);
pthread_kill(workerbees[tid], SIGUSR1);
sleep(2);
// Remove this and sem_wait will stay blocked
sem_post(&queue.work);
sleep(2);
return(0);
}
我知道的printf是不出声的信号处理程序,但只为它赫克,如果我删除它,我得到了相同的结果。
这些人是sem_post结果:
I am pthread 0x7f7fffc00000
Bee: I am pthread 0x7f7ff6c00000
Bee: got RC = 0 and errno = 0
Signal: I am pthread 0x7f7ff6c00000
并与sem_post:
I am pthread 0x7f7fffc00000
Bee: I am pthread 0x7f7ff6c00000
Bee: got RC = 0 and errno = 0
Signal: I am pthread 0x7f7ff6c00000
Bee: got RC = 0 and errno = 4
我知道我并不真的需要解锁并可以简单地做一个退出为主,但无论如何,我想看到它工作。我使用sem_wait的原因是因为我希望保持工作线程活着,并且一旦有来自Postfix的新客户端连接,就用sem_post从主线程中等待最长的工作线程。我不想一直执行pthread_create,因为我会每秒接收多次呼叫,并且我不想失去速度,并且使Postfix无法响应新的smtpd客户端。这是Postfix的一个policydaemon,服务器很忙。
我在这里错过了什么吗? NetBSD刚刚搞砸了吗?
会出现这种情况,如果你正确使用的sigaction?现在你将大量垃圾传递给了sigaction(),也许你得到了SA_RESTART标志集。您绝对需要初始化您的'struct sigaction sa;',或者执行'struct sigaction sa = {0};''或'memset(&sa,0,sizeof sa);' – nos
感谢您的提示,我得到了相同的结果...... – Saskia
至少在NetBSD 7.0 amd64上可以正常工作,并且我得到了'Bee:得到了RC = -1和errno = 4'(注意,你应该删除'extern int errno',声明errno就是这样,在多线程程序中是错误的) – nos