【ros多线程】C++多线程ROS程序CTRL C无法退出问题解决

1. 问题现象
  • 现象1: CTRL+C 无法退出正在运行的C++多线程ROS程序
  • 现象2:CTRL+Z 强制结束进程后top查看仍然有进程残留
  • 现象3:通过 kill -9 pid 彻底结束ROS进程
2. 问题原因
  • 在linux程序中,当用户按下CTRL+C命令后,程序可能接收到SIGINT中断信号(或 SIGTERM终止信号),但是如果程序正在执行多线程程序等,SIGINT信号可能被忽略或阻止,可能只有当前接收到SIGINT的子线程会退出,但是程序并不能优雅地停止
  • CTRL+Z发送SIGSTOP暂停信号,进程从前台转入后台并暂停,任务并没有结束只是维持挂起状态
  • kill -9发送SIGKILL终止信号,即exit信号,该信号不会被系统阻塞,能立即终止进程即子进程,因而能顺利退出程序,但是被杀死的进程没有机会告诉其父进程它已收到终止信号,可能导致创建僵尸进程
3. 解决方案
  • 可以通过设置信号处理函数来进行处理,以便在接收到SIGINT信号时清理资源退出程序
  • 设置信号处理函数,确保主线程能够接收到并处理这个信号,从而实现优雅地退出
4. 代码实现与测试
  • 利用signal()函数将SignalHandler注册为SIGINT或SIGTERM信号处理程序,停止ros spin循环

    #include <signal.h>
    
    void SignalHandler(int signal)
    {
    	// 还可以停止ros spinner对象,如果不用可注释掉
    	spinner->stop();
    	
    	// 1. 向其他ros节点publish停止信号
    	node_stop_msg = xxx
    	your_pub.publish(node_stop_msg);
    
    	// 2. 节点内如果有控制线程运行的标志位,如atomic<bool> keep_threads_running;
    	keep_threads_running = false;
    
    	// 3. 默认调用shutdown函数,通知ROS节点安全的关闭,导致ros::spin() / rclcpp::spin()退出
    	ros::shutdown();	// ROS 1
    	rclcpp::shutdown();	// ROS 2
    }
    
    // ROS 1 主程序调用示例
    int main(int argc, char** argv)
    {
    	ros::init(argc, argv, "your_node_name", ros::init_options::NoSigintHandler);
    	ros::NodeHandle nh;
    
    	// This must be set after the first NodeHandle is created.
    	signal(SIGINT, SignalHandler);	// 重载默认的signal handler函数
    	signal(SIGTERM, SignalHandler);	// SIGTERM信号也可添加处理函数
    	
    	ros::spin();
    	return 0;
    }
    
    // ROS 2主程序调用示例
    int main(int argc, char** argv)
    {
    	rclcpp::init(argc, argv);
    	rclcpp::executors::SingleThreadedExecutor executor;
    	auto your_node = std::make_shared<YourNodeClass>();
    	executor.add_node(your_node->get_node_base_interface());
    
    	std::thread your_sub_thread(xxx);
    	
    	signal(SIGINT, SignalHandler);
    	signal(SIGTERM, SignalHandler);
    	
    	executor.spin();
    	
    	your_sub_thread.join();	// 关卡
    
    	rclcpp::shutdown();
    	return 0;
    }
    

 


 
创作不易,如有帮助,请 点赞 收藏 支持
 


 

[参考文章]

[1]. SIGTERM和SIGKILL信号的区别
[2]. ctrl c退出ros程序
[3]. ros c++程序signal函数功能和实现

created by shuaixio, 2024.04.15

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值