pthread_cond_signal调用触发线程挂起卡死问题排查
我查阅了多个相关技术主题的资料,但暂未找到当前问题的答案,非常欢迎大家提供建议。
问题背景
我目前在开发一个大型项目,出现问题的相关代码片段如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <time.h> #include <sys/time.h> #include <unistd.h> #include <pthread.h> static pthread_mutex_t mutex; static pthread_cond_t cond; static char *timestamp() { time_t rawtime; struct tm *timeinfo; char *stamp; time(&rawtime); timeinfo = localtime(&rawtime); stamp = asctime(timeinfo); stamp[strlen(stamp) - 1] = '\0'; return stamp; } static void *monitor(void *ctx) { int ret; struct timeval now; struct timespec timeout = { 0 }; while (1) { gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec + 1; pthread_mutex_lock(&mutex); if (!(ret = pthread_cond_timedwait(&cond, &mutex, &timeout))) { printf("%s [%s] Signaled successfully!\n", timestamp(), __FUNCTION__); } else if (ret == ETIMEDOUT) printf("%s [%s] Timed out!\n", timestamp(), __FUNCTION__); pthread_mutex_unlock(&mutex); } return NULL; } int main() { pthread_t tid; if (pthread_mutex_init(&mutex, NULL) < 0) { perror("mutex"); return -1; } if (pthread_cond_init(&cond, NULL) < 0) { perror("cond"); pthread_mutex_destroy(&mutex); return -1; } if (pthread_create(&tid, NULL, monitor, NULL) < 0) { perror("create()"); pthread_cond_destroy(&cond); pthread_mutex_destroy(&mutex); return -1; } pthread_detach(tid); srand(time(NULL)); while (1) { int delay = rand() % 5 + 1; printf("%s [main] Waker is sleeping for %d sec\n", timestamp(), delay); sleep(delay); printf("%s [main] Signaling...\n", timestamp()); pthread_mutex_lock(&mutex); printf("%s [main] Lock aquired...\n", timestamp()); pthread_cond_signal(&cond); printf("%s [main] Signaled. Releasing...\n", timestamp()); pthread_mutex_unlock(&mutex); } pthread_cond_destroy(&cond); pthread_mutex_destroy(&mutex); return 0; }
问题现象
每当[main]线程执行到pthread_cond_signal位置,且monitor线程的pthread_cond_timedwait正处于等待状态(未触发超时)时,程序就会发生卡死。
我了解到调用pthread_cond_signal前持有互斥锁是推荐的最佳实践,也查阅了多个相关技术帖子,排查过以下可能原因但均不符合我的场景:
- 线程进入等待前提前销毁cond或mutex引发挂起
- *spurious wakes up(虚假唤醒)*导致卡死
我也曾猜测该异常与ulimit -s/-i配置有关,但将对应参数设置为unlimited后问题仍然存在。出现卡死时[monitor]线程会和main线程一同阻塞。
更新记录
更新1
程序卡死时的运行输出如下:
Wed Jun 8 13:34:10 2022 [main] Waker is sleeping for 4 sec Wed Jun 8 13:34:10 2022 [monitor] Timed out! Wed Jun 8 13:34:11 2022 [monitor] Timed out! Wed Jun 8 13:34:12 2022 [monitor] Timed out! Wed Jun 8 13:34:13 2022 [monitor] Timed out! Wed Jun 8 13:34:14 2022 [main] Signaling... Wed Jun 8 13:34:14 2022 [main] Lock acquired... /* 之后无任何输出 */
更新2
我将上述示例重构为使用pthread_cond_wait的最简逻辑,代码如下:
// monitor线程逻辑 pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); // main线程逻辑 pthread_mutex_lock(&mutex); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex);
重构后调用pthread_cond_signal仍然会出现挂起,因此我怀疑问题来自操作系统层面。我目前仅知道ulimit设置的栈大小过小会引发栈溢出,进而导致这类与架构相关、在我环境中可100%复现的卡死,想了解是否存在其他会影响pthread行为的特殊系统配置。
内容的提问来源于stack exchange,提问作者Volodymyr
相关产品推荐
相关产品推荐

