Как правильно управлять pthread - PullRequest
0 голосов
/ 03 марта 2019

У меня иногда возникают случайные проблемы с присоединением к pthread.Я могу просто сказать, что поток не застрял в взаимоблокировке с мьютексом при сбое соединения.Большую часть времени поток простаивает (системный вызов сна), когда тайм-аут произошел при соединении.

Моя потребность является базовой.Способ начать / остановить поток из основного потока.Поэтому мне не нужно помещать мьютекс в менеджер запуска / остановки в переменной состояния pthread.Поток работает как бесконечный цикл большую часть времени.Все мои темы спроектированы с одинаковым скелетом.Функция запуска и остановки.Определение функции потока.У меня есть глобальная переменная g_event_ctx для хранения текущего состояния потока. работает , чтобы знать, что мне нужно отменить его. is_joinable чтобы узнать, нужно ли мне присоединиться к ветке.Более того, у меня есть системный вызов sleep / read / write для всех моих функций потока (точка отмены!)

typedef struct pthread_context
{
    pthread_t id;       /*!< pthread_t to be able to stop the thread later */
    int running;        /*!< allow to know if the thread is currently running */
    int is_joinable;    /*!< allow to know if the thread is joinable */
} str_pthread_context;

Код скелета:

   int start_x_manager (void)
    {
        pthread_t t_x;

        if (g_event_ctx.x_thread.is_joinable) return 0;

        PRINT_INFO ("Start x manager");

        // start push x thread
        if (pthread_create (&t_x, NULL, x_loop_thread, NULL))
            PRINT_ERR_GOTO ("error on pthread_create for x thread");
        pthread_setname_np(t_x, "x");
        g_event_ctx.x_thread.id = t_x;
        g_event_ctx.x_thread.is_joinable = 1;
        g_event_ctx.x_thread.running = 1;
        return 0;
    error:
        g_event_ctx.x_thread.running = 0;
        g_event_ctx.x_thread.is_joinable = 0;
        return 1;
    }

    int stop_x_manager (void)
    {
        struct timespec ts;

        if (!g_event_ctx.x_thread.is_joinable) return 0;
        PRINT_INFO ("Stop x manager");

        if (g_event_ctx.x_thread.running)
        {
            CHECK_ERR_GOTO (pthread_cancel(g_event_ctx.x_thread.id) != 0, "Cannot cancel x thread");
            g_event_ctx.x_thread.running = 0;
        }
        CHECK_ERR_GOTO (clock_gettime(CLOCK_REALTIME, &ts) == -1, "Cannot get clock time");
        ts.tv_sec += 5;
        CHECK_ERR_GOTO (pthread_timedjoin_np (g_event_ctx.x_thread.id, NULL, &ts) != 0, "Cannot join x_thread");
        g_event_ctx.x_thread.is_joinable = 0;
        return 0;
    error:
        g_event_ctx.x_thread.running = 0;
        g_event_ctx.x_thread.is_joinable = 0;
        return 1;
    }

Скелет функции потока:

void *x_loop_thread (void *arg __attribute__((__unused__)))
{

    CHECK_ERR_GOTO (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0, "Cannot set cancel state");
    CHECK_ERR_GOTO (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0, "Cannot set cancel state");

    PRINT_INFO ("Start x manager loop thread ...");

    pthread_cleanup_push(x_manager_cleanup, some_stuff);

    while (1)
    {
         // Do some stuff here
    }
    g_event_ctx.x_thread.running = 0;
    pthread_exit (NULL);
  error:
    g_event_ctx.x_thread.running = 0;
    pthread_cleanup_pop(1);
    pthread_exit (NULL);
}

CHECK_ERR_GOTO - это макрос, который проверяет условие, чтобы узнать, нужно ли мне перейти к метке ошибка .

В чем причиначто может объяснить время ожидания для pthread_timedjoin_np ?Еще один фрагмент кода, который повредил мой идентификатор потока?Есть ли проблема дизайна в моем скелете?

...