具有更多参数的信号处理程序

Signal handler with more parameters

我正在 Ubuntu 18.04.2 LTS 上使用 ROS Melodic 和 Gazebo 9.9.0。

我想在用户杀死节点时向机器人发送 "stop" 消息(全为零的 Twist 消息)。

为了处理 Ctrl.+C 事件,我使用这个:

/**
 * Override the default ros sigint handler to stop the robot when user press
 * Ctrl.+C.
 */
void sigintHandler(int sig)
{


  // All the default sigint handler does is call shutdown()
  ros::shutdown();
}

但是这个函数不允许传递更多的参数(我需要传递cmd_vel_pub)。

我已在主要功能上声明此发布者:

int main(int argc, char **argv)
{
  ros::init(argc, argv, "astar_controller");

  ros::NodeHandle n;

  // Override the default ros sigint handler.
  // This must be set after the first NodeHandle is created.
  std::signal(SIGINT, sigintHandler);

  /**
   * Topic where we are going to publish speed commands.
   */
  ros::Publisher cmd_vel_pub = n.advertise<geometry_msgs::Twist>(cmdTopic, 1000);

  // More code...
}

也许我可以将 cmd_vel_pub 声明为全局。

有什么方法可以将更多参数传递给 sigintHandler 还是我需要将其声明为全局参数?

可以从信号处理程序调用的函数列表有限,请参阅 man signal-safety。因此,从信号处理程序上下文中发送 Twist 消息可能是不可能的。

self-pipe trick常用于处理信号处理上下文之外的信号:

Maintain a pipe and select for readability on the pipe input. Inside the signal handler, write a byte (non-blocking, just in case) to the pipe output. Done.

除此之外,我建议将信号编号字节写入管道,这样您就可以对任何信号(如果适用)使用完全相同的信号处理程序和管道。

希望处理信号的线程必须等待管道的读取端变为可读,读取该字节并处理信号。可以使用事件循环(例如 selectepoll 等)或阻塞 read 调用来完成等待。

或者,您可以使用 signalfd 代替管道(请参阅此处的示例)。或 sigsuspend 阻塞并等待信号。