/* * sm_demo.c * 模拟 st_sm_deinit 的三种场景 * * 编译: gcc sm_demo.c -o sm_demo -lpthread * 运行: * ./sm_demo 1 worker 已经自己退出deinit 直接收尾 * ./sm_demo 2 worker 优雅退出deinit 等到后 join * ./sm_demo 3 worker 退不出deinit 超时后 detach * */ #include stdio.h #include stdlib.h #include string.h #include pthread.h #include unistd.h #include errno.h /* ---------------- 可调参数 ---------------- */ #define SM_DEINIT_WAIT_MS 1000 /* deinit 最多等 1 秒 */ #define SM_DEINIT_SLICE_MS 10 /* 每 10ms 查一次 */ /* ---------------- 全局状态机 ---------------- */ typedef struct { pthread_mutex_t lock; pthread_t worker; int worker_alive; int abort_req; int mode; /* 1/2/3决定 worker 行为 */ } sm_t; static sm_t g_sm; /* ---------------- worker 线程 ---------------- */ static void *worker_thread(void *arg) { (void)arg; printf([worker] start, mode%d\n, g_sm.mode); pthread_mutex_lock(g_sm.lock); g_sm.worker_alive 1; pthread_mutex_unlock(g_sm.lock); if (g_sm.mode 1) { /* 场景 1worker 干完活自己退出不等 abort */ printf([worker] mode 1: work 300ms then exit by itself\n); usleep(300 * 1000); } else if (g_sm.mode 2) { /* 场景 2worker 检查 abort收到就退 */ printf([worker] mode 2: wait for abort\n); while (1) { pthread_mutex_lock(g_sm.lock); int stop g_sm.abort_req; pthread_mutex_unlock(g_sm.lock); if (stop) break; usleep(10 * 1000); } printf([worker] mode 2: got abort, exit\n); } else { /* 场景 3worker 忽略 abort永远不退 */ printf([worker] mode 3: ignore abort, never exit\n); while (1) { usleep(10 * 1000); } } pthread_mutex_lock(g_sm.lock); g_sm.worker_alive 0; pthread_mutex_unlock(g_sm.lock); printf([worker] exit\n); return NULL; } /* ---------------- 初始化 ---------------- */ static int sm_init(int mode) { memset(g_sm, 0, sizeof(g_sm)); g_sm.mode mode; pthread_mutex_init(g_sm.lock, NULL); if (pthread_create(g_sm.worker, NULL, worker_thread, NULL) ! 0) { perror(pthread_create); return -1; } printf([init] worker created\n); return 0; } /* * sm_deinit —— 完全照搬 st_sm_deinit 的结构 * */ static void sm_deinit(void) { int i 0; int alive 0; pthread_t th 0; /* 第 1 段设 abort_req读出状态 */ pthread_mutex_lock(g_sm.lock); g_sm.abort_req 1; alive g_sm.worker_alive; th g_sm.worker; pthread_mutex_unlock(g_sm.lock); printf([deinit] alive%d, th%lu\n, alive, (unsigned long)th); /* 第 2 段worker 已死直接收尾 */ if (!alive) { if (th) { (void)pthread_join(th, NULL); pthread_mutex_lock(g_sm.lock); g_sm.worker 0; pthread_mutex_unlock(g_sm.lock); printf([deinit] joined dead worker\n); } pthread_mutex_destroy(g_sm.lock); printf([deinit] path 2: worker already dead, done\n); return; } /* 第 3 段轮询等待 */ printf([deinit] waiting for worker (max %d ms)...\n, SM_DEINIT_WAIT_MS); for (i 0; i SM_DEINIT_WAIT_MS / SM_DEINIT_SLICE_MS; i) { pthread_mutex_lock(g_sm.lock); alive g_sm.worker_alive; pthread_mutex_unlock(g_sm.lock); if (!alive) break; usleep(SM_DEINIT_SLICE_MS * 1000u); } /* 第 4 段等到了join 销毁锁 */ pthread_mutex_lock(g_sm.lock); if (!g_sm.worker_alive g_sm.worker) { th g_sm.worker; g_sm.worker 0; pthread_mutex_unlock(g_sm.lock); (void)pthread_join(th, NULL); pthread_mutex_destroy(g_sm.lock); printf([deinit] path 4: worker exited gracefully, done\n); return; } /* 第 5 段没等到detach 兜底 */ if (g_sm.worker) { (void)pthread_detach(g_sm.worker); g_sm.worker 0; g_sm.worker_alive 0; } pthread_mutex_unlock(g_sm.lock); printf([deinit] path 5: worker still busy, detached for process exit\n); } /* ---------------- main ---------------- */ int main(int argc, char *argv[]) { if (argc 2) { printf(usage: %s 1|2|3\n, argv[0]); printf( 1: worker exits by itself before deinit\n); printf( 2: worker exits gracefully on abort\n); printf( 3: worker never exits, deinit detaches\n); return 1; } int mode atoi(argv[1]); if (mode 1 || mode 3) { printf(mode must be 1/2/3\n); return 1; } printf( mode %d \n, mode); if (sm_init(mode) ! 0) return 1; /* 不同场景等待时间不同 */ if (mode 1) { /* 等 worker 自己死 */ sleep(1); } else if (mode 2) { /* 等 worker 起来 */ sleep(1); } else { /* 等 worker 起来 */ sleep(1); } printf([main] call sm_deinit\n); sm_deinit(); printf([main] done\n); return 0; }代码里面的知识点一张图总结为什么进程要退出worker 可能还在跑 │ ▼ 不能直接杀丢数据、坏状态 │ ▼ 优雅退出通知 等待 收尾 │ ├─ 通知 → abort_req ├─ 知状态 → worker_alive加锁保护 ├─ 等待 → 轮询 超时 ├─ 等到了 → join 销毁锁 └─ 等不到 → detach 兜底不销毁锁