I need to handle SIGINT in my console application, I found many examples about sa_flags = 0; of sigaction structure - and it's mean getchar will be aborted and return -1. But this is not working with multithreading
Look at my code
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();
}
I want to interrupt getchar on Ctrl+C - similar code works just fine in single thread version (without std::thread stuff), but not in multithread. Please help me anyone - I am already stuck in this problem on whole day
1 Answer 1
Finally I found the right solution. SIGINT signal interrupts getchar operation only if this signal sent to the same thread with getchar. So if your application have tons of threads - we have situation in which probability of catching SIGINT in right thread is very small. So you will be pending getchar infinitely....
But! if we will carafully read pthread documentation about pthread_kill function we can see this line
pthread_kill - send a signal to a thread
pthread_kill - not killing thread in fact it's send signal. Eureka! We can resend signal SIGINT into the right thread. See code below
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();
}
1 Comment
getchar, and found the solution to the thread problem before I even had it myself. It became part not only of my code but also of this blog post.Explore related questions
See similar questions with these tags.
getchar()is interrupted by the signal then you must make sure that the signal is delivered to its thread by blocking it in all other threads.pthread_killdirects a signal to a specific thread, not to a whole process. You're welcome for being nudged in the right direction.