Я новичок в семафорах и хочу добавить многопоточность в свою программу, но я не могу обойти следующую проблему: sem_wait() должен иметь возможность получать EINTR и разблокировать, если бы я не делал 'установите флаг SA_RESTART. Я отправляю SIGUSR1 в рабочий поток, который блокируется в sem_wait(), он получает сигнал и прерывается, но он будет продолжать блокироваться, и поэтому он никогда не даст мне код возврата -1 вместе с errno = EINTR , Однако, если я делаю sem_post из основного потока, он будет разблокирован, дайте мне errno EINTR, но RC из 0. Я полностью озадачен этим поведением. Это какая-то странная реализация NetBSD, или я делаю что-то неправильно здесь? Согласно странице man, 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, заключается в том, что я хочу, чтобы рабочие потоки были живы и разбудили одну из них, ожидающую самого длинного из основного потока с помощью sem_post, как только появится новое клиентское соединение из Postfix. Я не хочу делать pthread_create все время, так как я буду получать вызовы несколько раз в секунду, и я не хочу терять скорость и не делаю Postfix невосприимчивым к новым клиентам smtpd. Это политик для Postfix, и сервер довольно занят.
Я что-то упустил? NetBSD просто испортил это?
произойдет ли это, если вы правильно использовать sigaction? Прямо сейчас вы передаете много мусора в sigaction(), и, возможно, вы установили флаг SA_RESTART. Вам абсолютно необходимо инициализировать 's saction s' s 's', либо '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