我需要在我的控制台应用程序中处理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 getchar\n");
auto c = getchar();
printf("after getchar\n");
}
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, ¤t);
std::thread trd(&run);
trd.join();
}
我想在Ctrl + C上中断getchar-类似的代码在单线程版本(没有std :: thread东西)下工作正常,但在多线程中却行不通。任何人都请帮助我-我已经整日陷入这个问题
最后我找到了正确的解决方案。仅当此信号与getchar发送到同一线程时,SIGINT信号才会中断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 getchar\n");
auto c = getchar();
printf("after getchar\n");
}
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, ¤t);
{
std::lock_guard lk(mtx);
trd.emplace(&run);
}
trd->join();
}