如何使用 SIGINT 在第二个线程中断 getchar



我需要在我的控制台应用程序中处理SIGINT,我找到了很多关于sa_flags = 0的例子; sigaction结构 - 这意味着getchar将被中止并返回-1。但这不适用于多线程

查看我的代码


int p[2];
FILE *stdin_writer = nullptr;
void int_handler(int signum)
{
//////do nothing
//////or write something into stdin..... also no help
//write(fileno(stdin), s, sizeof s - 1);
//////using pipes deadlocks application
//stdin_writer = fdopen(p[1], "w");
//fputc('g', stdin_writer);
}
void run()
{
//pipe(p);
//dup2(p[0], STDIN_FILENO);
printf("before getcharn");
auto c = getchar();
printf("after getcharn");
}
int main()
{
//////Setup SIGINT handler
struct sigaction sh;
sh.sa_handler = int_handler;
sigemptyset(&sh.sa_mask);
sh.sa_flags = 0;
sigaction(SIGINT, &sh, NULL);
return 0;
//////Setup console
termios _prev{ 0 };
// grab old terminal i/o settings
tcgetattr(0, &_prev);
// make new settings same as old settings 
auto current = _prev;
// disable buffered i/o
current.c_lflag &= ~ICANON;
// set no echo mode
current.c_lflag &= ~ECHO;
// use these new terminal i/o settings now
tcsetattr(0, TCSANOW, &current);
std::thread trd(&run);
trd.join();
} 

我想在Ctrl+C上中断 getchar - 类似的代码在单线程版本中工作得很好(没有 std::thread 的东西(,但在多线程中则不然。请帮助我任何人 - 我已经整天陷入这个问题

最后我找到了正确的解决方案。SIGINT 信号仅当此信号发送到与 getchar 相同的线程时才会中断 getchar 操作。因此,如果您的应用程序有大量线程 - 我们遇到的情况是在右线程中捕获 SIGINT 的可能性非常小。所以你将无限等待getchar....

但是!如果我们愿意阅读有关pthread_kill函数的 pthread 文档,我们可以看到这一行

pthread_kill - 向线程发送信号

pthread_kill - 实际上不是杀死线程,而是发送信号。尤里卡!我们可以将信号 SIGINT 重新发送到正确的线程中。请参阅下面的代码

std::optional<std::thread> trd;
std::mutex mtx;
void int_handler(int signum)
{
std::lock_guard lk(mtx);
if (trd && std::this_thread::get_id() != trd->get_id())
pthread_kill(trd->native_handle(), signum);
}
void run()
{
printf("before getcharn");
auto c = getchar();
printf("after getcharn");
}
int main()
{
//////Setup SIGINT handler
struct sigaction sh;
sh.sa_handler = int_handler;
sigemptyset(&sh.sa_mask);
sh.sa_flags = 0;
sigaction(SIGINT, &sh, NULL);
return 0;
//////Setup console
termios _prev{ 0 };
// grab old terminal i/o settings
tcgetattr(0, &_prev);
// make new settings same as old settings 
auto current = _prev;
// disable buffered i/o
current.c_lflag &= ~ICANON;
// set no echo mode
current.c_lflag &= ~ECHO;
// use these new terminal i/o settings now
tcsetattr(0, TCSANOW, &current);
{
std::lock_guard lk(mtx);
trd.emplace(&run);
}
trd->join();
} 

最新更新