mirror of
https://gitee.com/xiaohuolufeihua/bizhang_-obav.git
synced 2026-05-22 09:28:58 +00:00
uorb: fix several race conditions during topic initialization
Possible race conditions (they all happen between the check of existence of a topic and trying to create the node): - single instance, with multiple advertisers during the first advertise: both advertisers see the topic as non-existent and try to advertise it. One of them will fail, leading to an error message. This is the cause for telemetry_status advert failure seen in SITL in rare cases. - multi-instance: subscription to non-existing instance -> px4_open fails, and the subscriber tries to create the node. If during that time a publisher publishes that instance, the subscriber will get (instance+1) (or fails if the max number of instances is exceeded). This is a race that goes pretty much unnoticed. - multi-instance: 2 publishers can get the same instance (if is_published() is false in case both have not published data yet). This can also go unnoticed. Therefore the patch changes where _advertised is set: it is now set directly during the advertisement instead of during publication.
This commit is contained in:
@@ -327,14 +327,12 @@ int uORB::Manager::orb_get_interval(int handle, unsigned *interval)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uORB::Manager::node_advertise(const struct orb_metadata *meta, int *instance, int priority)
|
||||
int uORB::Manager::node_advertise(const struct orb_metadata *meta, bool is_advertiser, int *instance, int priority)
|
||||
{
|
||||
int ret = PX4_ERROR;
|
||||
|
||||
/* fill advertiser data */
|
||||
|
||||
if (get_device_master()) {
|
||||
ret = _device_master->advertise(meta, instance, priority);
|
||||
ret = _device_master->advertise(meta, is_advertiser, instance, priority);
|
||||
}
|
||||
|
||||
/* it's PX4_OK if it already exists */
|
||||
@@ -384,7 +382,7 @@ int uORB::Manager::node_open(const struct orb_metadata *meta, bool advertiser, i
|
||||
if (fd < 0) {
|
||||
|
||||
/* try to create the node */
|
||||
ret = node_advertise(meta, instance, priority);
|
||||
ret = node_advertise(meta, advertiser, instance, priority);
|
||||
|
||||
if (ret == PX4_OK) {
|
||||
/* update the path, as it might have been updated during the node_advertise call */
|
||||
@@ -396,7 +394,7 @@ int uORB::Manager::node_open(const struct orb_metadata *meta, bool advertiser, i
|
||||
}
|
||||
}
|
||||
|
||||
/* on success, try the open again */
|
||||
/* on success, try to open again */
|
||||
if (ret == PX4_OK) {
|
||||
fd = px4_open(path, (advertiser) ? PX4_F_WRONLY : PX4_F_RDONLY);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user