У меня иногда возникают случайные проблемы с присоединением к 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 ?Еще один фрагмент кода, который повредил мой идентификатор потока?Есть ли проблема дизайна в моем скелете?