Я бы также порекомендовал использовать выбор или другие не основанные на сигнале средства завершения вашего потока. Одна из причин, по которой у нас есть темы, - попытаться уйти от безумия сигнала. Тем не менее ...
Обычно используется pthread_kill () с SIGUSR1 или SIGUSR2 для отправки сигнала потоку. Другие предлагаемые сигналы - SIGTERM, SIGINT, SIGKILL - имеют семантику всего процесса, которая может вас не заинтересовать.
Что касается поведения при отправке сигнала, я думаю, что это связано с тем, как вы обрабатывали сигнал. Если у вас нет установленного обработчика, действие этого сигнала по умолчанию применяется, но в контексте потока, который получил сигнал. Так, например, SIGALRM будет «обрабатываться» вашим потоком, но обработка будет состоять из завершения процесса - вероятно, не желаемого поведения.
Получение сигнала потоком, как правило, прерывает его при чтении с помощью EINTR, если только он действительно не находится в таком непрерывном состоянии, как упомянуто в предыдущем ответе. Но я думаю, что это не так, иначе ваши эксперименты с SIGALRM и SIGIO не остановили бы процесс.
Возможно ли ваше чтение в каком-то цикле? Если чтение завершается с возвратом -1, то вырвитесь из цикла и выйдите из потока.
Вы можете поиграть с этим очень неаккуратным кодом, который я собрал, чтобы проверить мои предположения - на данный момент я нахожусь в паре часовых поясов от моих книг по POSIX ...
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
int global_gotsig = 0;
void *gotsig(int sig, siginfo_t *info, void *ucontext)
{
global_gotsig++;
return NULL;
}
void *reader(void *arg)
{
char buf[32];
int i;
int hdlsig = (int)arg;
struct sigaction sa;
sa.sa_handler = NULL;
sa.sa_sigaction = gotsig;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
if (sigaction(hdlsig, &sa, NULL) < 0) {
perror("sigaction");
return (void *)-1;
}
i = read(fileno(stdin), buf, 32);
if (i < 0) {
perror("read");
} else {
printf("Read %d bytes\n", i);
}
return (void *)i;
}
main(int argc, char **argv)
{
pthread_t tid1;
void *ret;
int i;
int sig = SIGUSR1;
if (argc == 2) sig = atoi(argv[1]);
printf("Using sig %d\n", sig);
if (pthread_create(&tid1, NULL, reader, (void *)sig)) {
perror("pthread_create");
exit(1);
}
sleep(5);
printf("killing thread\n");
pthread_kill(tid1, sig);
i = pthread_join(tid1, &ret);
if (i < 0)
perror("pthread_join");
else
printf("thread returned %ld\n", (long)ret);
printf("Got sig? %d\n", global_gotsig);
}