diff options
author | mvglasow <michael -at- vonglasow.com> | 2015-10-18 14:50:59 +0200 |
---|---|---|
committer | mvglasow <michael -at- vonglasow.com> | 2015-10-18 14:50:59 +0200 |
commit | 933c69e222e9bc5a5d23076ca1ad3651bb184e36 (patch) | |
tree | d2869678558d9991f8140b9bf2d7e0a672b9e712 /navit/navigation.c | |
parent | 8f1f8bc00bacb2f6a9e421029d8263906464e79b (diff) | |
download | navit-933c69e222e9bc5a5d23076ca1ad3651bb184e36.tar.gz |
Fix:core:Fix race condition on position update
Signed-off-by: mvglasow <michael -at- vonglasow.com>
Diffstat (limited to 'navit/navigation.c')
-rw-r--r-- | navit/navigation.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/navit/navigation.c b/navit/navigation.c index 969eb13ad..7c0609d81 100644 --- a/navit/navigation.c +++ b/navit/navigation.c @@ -3644,6 +3644,7 @@ navigation_call_callbacks(struct navigation *this_, int force_speech) static void navigation_update_done(struct navigation *this_, int cancel) { int incr = 0; + struct map_rect *mr = this_->route_mr; if (this_->idle_ev) event_remove_idle(this_->idle_ev); @@ -3665,13 +3666,21 @@ navigation_update_done(struct navigation *this_, int cancel) { navigation_call_callbacks(this_, FALSE); } } - map_rect_destroy(this_->route_mr); - this_->route_mr = NULL; + /* + * In order to ensure that route_mr holds either NULL or a valid pointer at any given time, + * always pass a copy of it to map_rect_destroy() and set route_mr to NULL prior to calling + * map_rect_destroy(). The reason is that map_rect_destroy() for a route map may call idle + * callback functions before it returns. If one of these calls results in a call to + * navigation_update(), a race condition will occur. For the same reason, status must be reset + * before the call to map_rect_destroy(). + */ this_->status = status_none; + this_->route_mr = NULL; + map_rect_destroy(mr); } /** - * @brief Idle loop function to retrieve items from the route map. + * @brief Idle callback function to retrieve items from the route map. * * @param this_ Points to the navigation object. The caller is responsible for initializing its * {@code route_mr} member. After processing completes, the {@code route_mr} member will no longer @@ -3696,8 +3705,10 @@ navigation_update_idle(struct navigation *this_) { } while (count > 0) { - if (!(ritem = map_rect_get_item(this_->route_mr))) + if (!(ritem = map_rect_get_item(this_->route_mr))) { + this_->status &= ~(status_has_ritem); break; + } this_->status |= status_has_ritem; if ((ritem)->type == type_route_start && this_->turn_around > -this_->turn_around_limit+1) this_->turn_around--; @@ -3762,9 +3773,7 @@ navigation_update(struct navigation *this_, struct route *route, struct attr *at if (attr->u.num != route_status_path_done_new && attr->u.num != route_status_path_done_incremental) { if (this_->status & status_busy) { navigation_update_done(this_, 1); - return; } - return; } |