如何从其他线程通过SigInt退出replxx命令行工具?
如何在主线程触发独立线程中replxx的退出操作
方案1:利用信号机制中断replxx的阻塞输入
replxx的input()函数在阻塞时会响应信号,我们可以通过主线程向replxx线程发送自定义信号,配合线程安全的退出标志实现退出:
实现步骤
- 用
std::atomic<bool>定义线程安全的退出标志 - 在replxx线程中注册信号处理函数,收到信号时设置退出标志为
true - replxx线程循环调用
input(),一旦检测到退出标志或input()返回空,立即终止循环 - 主线程触发退出时,向replxx线程发送指定信号
代码示例
#include <replxx.hxx> #include <atomic> #include <thread> #include <signal.h> #include <unistd.h> std::atomic<bool> g_quit(false); void sig_handler(int) { g_quit = true; } void replxx_thread() { // 注册SIGUSR1信号处理函数 signal(SIGUSR1, sig_handler); replxx::Replxx rx; rx.install_window_change_handler(); while (!g_quit) { char const* input = rx.input("> "); if (input == nullptr || g_quit) { break; } // 处理输入逻辑 rx.history_add(input); free(const_cast<char*>(input)); } } int main() { std::thread repl_thread(replxx_thread); // 主线程业务逻辑,示例为等待用户输入触发退出 printf("Press enter to quit...\n"); getchar(); // 向replxx线程发送退出信号 pthread_kill(repl_thread.native_handle(), SIGUSR1); repl_thread.join(); return 0; }
注意事项
- 信号处理函数仅能调用线程安全的函数,
std::atomic赋值操作是安全的 - Windows平台需替换
pthread_kill为SetConsoleCtrlHandler等平台相关API
方案2:使用管道唤醒replxx线程(更可靠的跨平台方案)
信号机制存在多线程投递不确定性,管道方案通过IO监听实现更稳定的线程间通知:
实现步骤
- 创建匿名管道实现主线程与replxx线程的通信
- replxx线程用
select()同时监听标准输入和管道读端 - 主线程触发退出时,向管道写端写入数据,唤醒replxx线程
- replxx线程检测到管道数据后,设置退出标志并终止循环
代码示例
#include <replxx.hxx> #include <atomic> #include <thread> #include <unistd.h> #include <sys/select.h> int g_pipe_fd[2]; std::atomic<bool> g_quit(false); void replxx_thread() { replxx::Replxx rx; rx.install_window_change_handler(); fd_set read_fds; int max_fd = std::max(STDIN_FILENO, g_pipe_fd[0]); while (!g_quit) { FD_ZERO(&read_fds); FD_SET(STDIN_FILENO, &read_fds); FD_SET(g_pipe_fd[0], &read_fds); // 监听标准输入与管道 int ret = select(max_fd + 1, &read_fds, nullptr, nullptr, nullptr); if (ret == -1) break; if (FD_ISSET(g_pipe_fd[0], &read_fds)) { // 收到退出通知 char buf[1]; read(g_pipe_fd[0], buf, 1); g_quit = true; break; } if (FD_ISSET(STDIN_FILENO, &read_fds)) { char const* input = rx.input("> "); if (input == nullptr) break; // 处理输入逻辑 rx.history_add(input); free(const_cast<char*>(input)); } } } int main() { // 创建管道 if (pipe(g_pipe_fd) == -1) { perror("pipe"); return 1; } std::thread repl_thread(replxx_thread); // 主线程业务逻辑 printf("Press enter to quit...\n"); getchar(); // 写入数据唤醒replxx线程 write(g_pipe_fd[1], "q", 1); repl_thread.join(); // 关闭管道 close(g_pipe_fd[0]); close(g_pipe_fd[1]); return 0; }
注意事项
- Windows平台需替换
pipe()为CreatePipe,select()为WaitForMultipleObjects - 确保所有文件描述符在线程退出后正确关闭
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

