我正在编写一个使用线程的c程序,并且我还希望捕获用户的Ctrl + C信号。所以,在我开始多线程之前,我让信号捕捉。信号捕获和线程终止的问题 - C
我的主线程(我的意思是除了程序运行的实际主线程),是一种处理用户输入的方法,并且我也将该线程加入主程序线程。
问题是,当测试并按Ctrl + C退出程序时,负责接收用户输入的线程不会关闭,直到我在键盘上点击“返回” - 就像它卡在无限循环中一样。
当通过键入'q'退出时,所有线程都会正常结束。
我使用全局变量exit_flag来指示线程完成其循环。
此外,在init_radio_stations方法还有另外一个单一线程的创建,在完全相同的方式循环 - 在exit_flag状态,而这还没有登录,接近正常
这里是我的主循环代码:
void main_loop()
{
status_type_t rs = SUCCESS;
pthread_t thr_id;
/* Catch Ctrl+C signals */
if(SIG_ERR == signal(SIGINT, close_server)) {
error("signal() failed! errno = ");
}
printf("\n~ Welcome to radio_server! ~\n Setting up %d radio stations... ", srv_params.num_of_stations);
init_radio_stations();
printf("Done!\n\n* Hit 'q' to exit the application\n* Hit 'p' to print stations & connected clients info\n");
/* Create and join a thread to handle user input */
if(pthread_create(&thr_id, NULL, &rcv_usr_input, NULL)) {
error("main_loop pthread_create() failed! errno = ");
}
if(pthread_join(thr_id, NULL)) {
error("main_loop pthread_join() failed! errno = ");
}
}
close_server方法:
void close_server(int arg)
{
switch(arg) {
case SIGINT: /* 2 */
printf("\n^C Detected!\n");
break;
case ERR: /* -1 */
printf("\nError occured!\n");
break;
case DEF_TO: /* 0 */
printf("\nOperation timed-out!\n");
break;
default: /* will handle USER_EXIT, and all other scenarios */
printf("\nUser abort!\n");
}
printf("Signaling all threads to free up all resources and exit...\n");
/* Update exit_flag, and wait 1 sec just in case, to give all threads time to close */
exit_flag = TRUE;
sleep(1);
}
而且rcv_usr_input处理代码:
void * rcv_usr_input(void * arg_p)
{
char in_buf[BUFF_SIZE] = {0};
while(FALSE == exit_flag) {
memset(in_buf, 0, BUFF_SIZE);
if(NULL == fgets(in_buf, BUFF_SIZE, stdin)) {
error("fgets() failed! errno = ");
}
/* No input from the user was received */
if('\0' == in_buf[0]) {
continue;
}
in_buf[0] = tolower(in_buf[0]);
if(('q' == in_buf[0]) && ('\n' == in_buf[1])) {
close_server(USER_EXIT);
} else {
printf("Invalid input!\nType 'q' or 'Q' to exit only\n");
}
}
printf("User Input handler is done\n");
return NULL;
}
我猜我的问题是有关加入使用rcv_usr_input我的主循环结束的线程,但我无法弄清楚究竟是什么造成这种行为。
我很乐意获得一些帮助,谢谢
通过信号处理程序(哦,男孩!混合线程和信号,*可能出错*),未定义的行为写入到'exit_flag'的非同步访问的数据竞争。 – EOF
@EOF不需要讽刺,使用线程和信号对我来说是新的,而且我仍然在学习:) 如何在使用线程时处理信号?我总是很高兴学到新东西 – Adiel
该代码有几个问题,你可以在这个网站上研究。 'pthread_create'返回一个错误代码(它不会设置'errno')。 'exit_flag'可能需要'volatile sig_atomic_t',但这不会帮助threads_之间的可见性问题。 'printf'不是异步信号安全的。当错误_and_成功(即EOF)时,'fgets'可以返回NULL。 – pilcrow