を使用して特定のスレッドにシグナルを送信できますpthread_kill()
。または、GNU 固有であることを気にしない場合は、pthread_sigqueue()
(1 つを指定するint
かvoid *
、ハンドラーが を介してアクセスできますinfo->si_value
) を使用して、シグナルを送信できます。
プロセスのシグナルごとに 1 つのシグナル ハンドラーしかありません。これは、特定のシグナルが、たまたまどのスレッドであっても、常に同じハンドラー関数を呼び出すことを意味します。1 つのスレッドが新しいシグナル ハンドラを設定すると、すべてのスレッドのシグナル ハンドラが変更されます。
ただし、回避策は簡単です。スレッドごとの関数ポインターを使用して、シグナル ハンドラーが呼び出す関数を定義します。シグナル ハンドラーの制限を覚えておいてください。シグナル ハンドラーでは非同期シグナル セーフ関数のみを使用できます。
/* Simplify by defining the signal handler function type, assume SA_SIGINFO */
typedef void (*signal_handler_t)(int, siginfo_t *, void *);
/* Per-thread variable pointing to the desired function */
static __thread signal_handler_t thread_handler = NULL;
/* Process-wide actual signal handler */
static void signal_handler(int signum, siginfo_t *info, void *context)
{
signal_handler_t func;
func = __sync_fetch_and_or(&thread_handler, (signal_handler_t)0);
if (func)
func(signum, info, context);
}
アトミック ロード ( __sync_fetch_and_or()
) を使用すると、単純なアトミック ストアを使用して、シグナルをブロックすることなく、いつでもスレッドごとのハンドラーを簡単に変更できます。機能への切り替えnew_thread_handler
はその後です
signal_handler_t func;
do {
func = thread_handler;
} while (!__sync_bool_compare_and_swap(&thread_handler, func, new_thread_handler));
関数スイッチと関数スイッチは両方とも 1 つの__sync_fetch_and_or()
C++11 スタイルの__atomic_
呼び出しで置き換えることができますが、最近の GCC がまだ十分にないので、古いスタイルの__sync_
呼び出しをまだ使用しています。
POSIX は、リアルタイムシグナル 、SIGRTMIN+0
、SIGRTMIN+1
..、もサポートしていますSIGRTMAX
。それらには、複数のそれらを同時に保留できるという追加の利点があります。それらは、従来の信号よりもこの種のものにはるかに適しています.