О поведении pthread_kill () - PullRequest
       16

О поведении pthread_kill ()

3 голосов
/ 28 февраля 2012

У меня вопрос о поведении pthread_kill ().

Вот небольшой код, который я пробую:

void my_handler1(int sig)
{
    printf("my_handle1: Got signal %d, tid: %lu\n",sig,pthread_self());
    //exit(0);
}

void *thread_func1(void *arg)
{
    struct sigaction my_action;
    my_action.sa_handler = my_handler1;
    my_action.sa_flags = SA_RESTART;
    sigaction(SIGUSR1, &my_action, NULL);
    printf("thread_func1 exit\n");
}


void *thread_func2(void *arg)
{
    int s;
    s = pthread_kill(tid1_g,SIGUSR1);
    if(s)
            handle_error(s,"tfunc2: pthread_kill");

    printf("thread_func2 exit\n");
}


int main()
{
    int s = 0;
    pthread_t tid1;

    s = pthread_create(&tid1,NULL,thread_func1,NULL);
    if(s)
            handle_error(s,"pthread_create1");

    tid1_g = tid1;
    printf("tid1: %lu\n",tid1);
    s = pthread_join(tid1,NULL);
    if(s)
            handle_error(s, "pthread_join");

    printf("After join tid1\n");

    pthread_t tid3;
    s = pthread_create(&tid3,NULL,thread_func2,NULL);
    if(s)
            handle_error(s,"pthread_create3");

    s = pthread_join(tid3,NULL);
    if(s)
            handle_error(s, "pthread_join3");

    printf("After join tid3\n");
    return 0;
}

Вывод, который я получаю:

tid1: 140269627565824
thread_func1 exit
After join tid1
my_handle1: Got signal 10, tid: 140269627565824
thread_func2 exit
After join tid3

Итак, хотя я вызываю pthread_kill () для потока, который уже завершен, обработчик для этого потока все еще вызывается. Разве pthread_kill () не должен возвращать ошибку (ESRCH) в случае, если поток не существует?

Ответы [ 3 ]

7 голосов
/ 28 февраля 2012

Любое использование (*) pthread_t для потока после его времени жизни (то есть после успешного возврата pthread_join или после завершения потока в отключенном состоянии) приводит к undefinedповедение .Вы должны ожидать ESRCH только в том случае, если pthread_t все еще действует, то есть если вы еще не присоединились к потоку.В противном случае все ставки выключены.

Примечание. Под «использованием» (*) я подразумеваю передачу его функции pthread_ в стандартной библиотеке.Насколько я могу судить, простое присвоение ее другой переменной pthread_t или иная передача ее между вашими собственными функциями без «использования» не приводит к UB.

3 голосов
/ 28 февраля 2012

В соответствии с этим SO thread говорит, что передача сигнала в уже мертвый поток (только если поток был присоединен или завершен) приводит к неопределенному поведению!

EDIT : Найден поток , который явно цитирует последнюю спецификацию POSIX, которая указывает на поведение, которое не определено.Спасибо R .. за правильные указатели!

0 голосов
/ 14 мая 2016

Вопрос заданный здесь (Как определить, жив ли pthread) был помечен как дубликат этого вопроса.

Но я считаю, что этот пост просто разъясняет поведение pthread_kill и подтверждает, что он не гарантирует правильного поведения, если pthread_kill вызывается с идентификатором, который больше не действителен. Следовательно, pthread_kill не может использоваться, чтобы знать, является ли поток живым или нет, как если бы поток был присоединен ранее, идентификатор не был бы действительным или был бы повторно использован, и то же самое имеет место, если он был отсоединен как ресурсы может быть восстановлено, если поток был прерван.

Таким образом, чтобы определить, является ли поток живым (вопрос специально задается для присоединяемых потоков), я мог бы подумать только об одном решении, как показано ниже:

Использовать некоторые глобальные данные / память, к которым могут обращаться оба потока, и сохранять там состояние возврата / выхода потока, чей статус необходимо определить. Другие потоки могут проверить эти данные / местоположение, чтобы получить их статус. (Очевидно, это предполагает, что поток завершился нормально, т. Е. Присоединился или отсоединился).

Например:

Have a global bool named as "bTerminated" initialized with "FALSE" and in
the handler function of this thread either make it as "TRUE" before
returning or modify it once it is returned to the caller (i.e where you have
called `pthread_join` for this thread). Check for this variable in any other
threads where you want to know if this thread is alive. Probably it will be
straight to implement such a logic which fits into your original code.
...