Как собрать статус выхода из нити (используя соединение) при отмене - PullRequest
0 голосов
/ 26 января 2020

Я пытаюсь отменить поток от вызывающего или вызывающего абонента, но оба сбой программы

Но если я присоединяюсь, я получаю правильное состояние выхода.

как получить статус выхода правильно на странице руководства pthread_cancel

указано ниже

После завершения отмененного потока соединение с этим потоком с помощью pthread_join (3) получает PTHREAD_CANCELED в качестве состояния выхода потока. (Присоединение к ветке - единственный способ узнать, что отмена завершена.)

#include <stdio.h>
#include <pthread.h>

void *thread_func(void *arg);
int errNum = 3;
int main()
{
    pthread_t t_id;
    void *status;

    // on success pthread_create return zero
    if(pthread_create(&t_id,NULL,thread_func,NULL) != 0){
        printf("thread creation failed\n");
        return 0;   
    }

    printf("thread created with id %u successfully\n",t_id);
    // status will be collecting the pthread_exit value
    // error numberis returned incase of error

//  pthread_cancel(t_id);

    if(pthread_join(t_id,&status) != 0){
        printf("join failed\n");

    }
    printf("thread %u exited with code %d\n", t_id, *(int *)status);
    return 0;
}

void *thread_func(void *arg)
{

    printf("Inside thread_func :%u\n",pthread_self());
    //the arguments of pthread_exit should not be from local space, as it will be collected in caller using join
    //pthread_exit(&errNum);

    // if we return it may cause seg fault as we are trying to print the value from ptr(status)
    //return ;  
    pthread_cancel(pthread_self());
}

1 Ответ

1 голос
/ 27 января 2020

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

Пример:

    void *status;

    // ...

    if (pthread_join(t_id, &status) != 0) {
        // pthread_join failed
    } else if (status == PTHREAD_CANCELED) {
        // successfully joined a thread that was cancelled
        // 'status' MUST NOT be dereferenced
    } else {
        // successfully joined a thread that terminated normally
        // whether 'status' may be dereferenced or how else it may be
        // used depends on the thread
    }

Стоит отметить, что формулировка * Страница справочника 1035 * немного быстрая и свободная. Потоки не имеют «состояния выхода» в том смысле, в каком они существуют в процессах, а фактические спецификации POSIX не используют этот термин в контексте потоков. Например, спецификации POSIX для pthread_join() говорят:

При возврате из успешного вызова pthread_join() с аргументом, отличным от NULL value_ptr, значение передается в pthread_exit() завершающим потоком должен быть доступен в месте, указанном value_ptr.

Это немного глоток по сравнению с формулировкой Linux, но он выбран очень точный.

Обратите внимание, что выбор типа void * здесь является намеренным и полезным. Это не просто тупой способ упаковки int. С помощью такого указателя поток может предоставить доступ к объекту любого типа, что может быть полезно для передачи информации о результате его вычислений. С другой стороны, потоки довольно часто отказываются от этой возможности и просто возвращают NULL. Но если поток действительно хочет предоставить целочисленный код таким способом, то он, скорее всего, предоставит int значение приведение к типу void *, а не указатель на объект типа int содержащий выбранное значение. В этом случае можно получить значение, приведя обратно к int, а не разыменовав указатель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...