我是新的信號量,並希望添加多線程到我的程序,但我無法解決以下問題: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