私はセマフォに不慣れで、自分のプログラムにマルチスレッドを追加したいと考えていますが、SA_RESTART フラグを設定していない限り、sem_wait() は EINTR を受信してブロックを解除できる必要があるという問題を回避できません。sem_wait() でブロックしているワーカー スレッドに SIGUSR1 を送信しています。シグナルを受信して中断されますが、その後ブロックし続けるため、errno = EINTR と一緒に -1 のリターン コードが返されることはありません。 . ただし、メイン スレッドから sem_post を実行すると、ブロックが解除され、EINTR の errno が返されますが、RC は 0 になります。この動作には完全に困惑しています。それは奇妙な NetBSD 実装ですか、それともここで何か間違ったことをしていますか? man ページによると、sem_wait は POSIX.1 (ISO/IEC 9945-1:1996) に準拠しています。簡単なコード:
#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 を常に実行したくはありません。1 秒間に複数回呼び出しを受信し、速度を落として Postfix を新しい smtpd クライアントに応答させたくないからです。これは Postfix のポリシーデーモンであり、サーバーは非常にビジーです。
ここで何か不足していますか?NetBSD はこれを台無しにしてしまったのでしょうか?