Why does my subscriber report multiple liveliness change events when I kill my publisher?

Note: Applies to RTI Connext 4.x and above.

Upon changing the liveliness lease duration of both the DataReader and DataWriter, and instrumenting the on_liveliness_changed() listener callback on the reader side, you will see the callback is called twice when you kill the publishing application. 

HelloMsg_subscriber.exe 10
 
HelloMsg subscriber sleeping for 4 sec...
on_liveliness_changed called      // publisher discovered
        alive_count = 1
        not_alive_count = 0
        alive_count_change = 1
        not_alive_count_change = 0
HelloMsg subscriber sleeping for 4 sec...
   msg_id: 0
   msg: "Hello (1)"
...

Kill publishing application

...
HelloMsg subscriber sleeping for 4 sec...
on_liveliness_changed called    
        alive_count = 0
        not_alive_count = 1
        alive_count_change = -1
        not_alive_count_change = 1
HelloMsg subscriber sleeping for 4 sec...
HelloMsg subscriber sleeping for 4 sec...
HelloMsg subscriber sleeping for 4 sec...
HelloMsg subscriber sleeping for 4 sec...
...
HelloMsg subscriber sleeping for 4 sec...
HelloMsg subscriber sleeping for 4 sec...
HelloMsg subscriber sleeping for 4 sec...
on_liveliness_changed called
        alive_count = 0
        not_alive_count = 0
        alive_count_change = 0
        not_alive_count_change = -1
HelloMsg subscriber sleeping for 4 sec...
HelloMsg subscriber sleeping for 4 sec...
HelloMsg subscriber sleeping for 4 sec...

In the attached example application, we configured the liveliness period for the DataReader and DataWriter to be 1 second. 

  1. When the DataReader first discovers the DataWriter, the LivelinessChanged event is generated because the DataReader has detected a new, active writer. So alive_count = 1 and alive_count_change = 1. When instrumented, the on_subscription_matched() callback is also triggered, indicating the DataReader has detected a matching DataWriter.
  2. When you stop the publisher’s process, after 1 second the DataReader will lose liveliness with the DataWriter. The  LivelinessChanged event happens because the DataReader lost liveliness with a matched DataWriter. So alive_count = 0, alive_count_change = -1, not_alive_count = 1, and not_alive_count_change = 1. Notice not_alive_count = 1; this means the DataWriter hasn’t been explicitly deleted, but it has violated its liveliness contract with the DataReader. The on_subscription_matched() callback will not be called because the DataReader is still “matched” with the DataWriter.
  3. After at least 100 seconds ( participant_liveliness_lease_duration), the participant's liveliness loss is detected. At this point, the LivelinessChanged event is generated because a matched DataWriter is purged from the system. Now alive_count = 0, alive_count_change = 0, not_alive_count = 0, and not_alive_count_change = -1. Notice not_alive_count_change = -1, because the matched DataWriter is no longer present and the DataReader cannot tell if it is “alive” or “not alive.” The on_subscription_matched() callback will be invoked in this case because the DataReader lost its “match” with the DataWriter.
Attachments: