0
$\begingroup$

Rosanswers logo

Consider the following example:

#include <ros/ros.h>
#include <std_msgs/String.h>

void connectCallback(const ros::SingleSubscriberPublisher&)
{
  ROS_INFO("connectCallback");
}

void disconnectCallback(const ros::SingleSubscriberPublisher&)
{
  ROS_INFO("disconnectCallback");
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "test_node");
  ros::NodeHandle nh;
  ros::Publisher pub = nh.advertise<std_msgs::String>("talk", 1, &connectCallback, &disconnectCallback);
  ros::Rate r(1);
  while (nh.ok())
  {
    ROS_INFO("Number of subscribers: %zu", pub.getNumSubscribers());
    ros::spinOnce();
    r.sleep();
  }
  return 0;
}

When subscribing using rostopic echo /talk, connectCallback is called immediately. However, when shutting down the rostopic process, the reported number of subscribers is still 1 until disconnectCallback gets called about one minute later. Why? Is there any way to shorten this timeout? When the publisher is active (i.e. publishing something in the loop), disconnectCallback is called immediately.

EDIT

Here is another subscriber (different from rostopic) that I used for testing with the same result:

#include <ros/ros.h>
#include <std_msgs/String.h>

void callback(const std_msgs::StringConstPtr& msg)
{
  std::cout << msg->data << std::endl;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "subscriber");
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe("talk", 1, &callback);

  ros::Time start_time = ros::Time::now();
  while (ros::ok() && (ros::Time::now() - start_time).toSec() < 10)
  {
    ros::spinOnce();
  }
  return 0;
}

Originally posted by Stephan on ROS Answers with karma: 1924 on 2012-01-17

Post score: 2


Original comments

Comment by Stephan on 2012-01-18:
@Lorenz: I tried that already, I'll edit the question to clarify this.

Comment by Lorenz on 2012-01-17:
I would guess that the rostopic process does not shutdown correctly and after a minute, your node notices that the socket is invalid. I would write a simple roscpp node that subscribes, stays connected for a while and then shuts down. If that works, you know it's rostopic's fault.

Comment by Stephan on 2012-01-17:
I just tried using a self-made subscriber, same result.

Comment by dornhege on 2012-01-17:
One guess would be that shutting down rostopic doesn't properly close the connection (although it should), so only when you try to publish the node realizes it's disconnected

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

This is ticketed at https://code.ros.org/trac/ros/ticket/3403. There I wrote:

I've noticed this issue with unsubscribe callbacks too. However, it's not true that they're never called; they do get called exactly 60s after you subscribe.

In practice this shouldn't normally be an issue. In each nodelet we use connect callbacks to control whether it hooks into a data source (camera or ROS topic). As long as it's getting data, it publishes some processed output. So if all subscribers to the output unsubscribe, the next call to publish() triggers the disconnect callback, which unhooks from the data source. So as long as you're streaming data, disconnects will be timely.

It's still annoying and can cause odd behavior in practice - e.g. if the register nodelet doesn't get the tf data it needs, it can't publish(), so it takes the full 60s to disconnect. So I'd like to see this fixed, or at least know why it happens.

Generally this hasn't been an issue for us - if we need the disconnect callback called immediately, it's because we're shutting down a publisher that's continuously spewing data. Do you have a use case where you require a timely disconnect callback for an inactive publisher?


Originally posted by Patrick Mihelich with karma: 4336 on 2012-01-18

This answer was ACCEPTED on the original site

Post score: 3


Original comments

Comment by Stephan on 2012-01-18:
Thanks Patrick, I'll mark your answer as accepted as the solution will come up in ticket 3403. Use case: a lazy node that subscribes to inputs if its output is needed and publishes dependent on the input data (object found). So if the object disappears, publish is not called. Similar to your tf ex.

$\endgroup$
0
$\begingroup$

Rosanswers logo

I have updated Issue 3403 with a comment. Without having delved deep into the internals of roscpp, Maybe the reported issue might have something to do with the time a closed socket spends in the TIME_WAIT state, which is configured by the tcp_fin_timeout parameter, that defaults to 60s:

cat /proc/sys/net/ipv4/tcp_fin_timeout
60

Originally posted by Adolfo Rodriguez T with karma: 3907 on 2012-01-18

This answer was NOT ACCEPTED on the original site

Post score: 2

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.