From 2c3952af66d6907f8a892d42d0034e91126b073a Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 27 Apr 2015 11:10:10 -0700 Subject: [PATCH] Avoid binding a shared_ptr in the work callback It's possible that the work callback can outlive the after callback, since work callback destruction and after callback execution happen in two different threads. This could account for the crash seen in https://github.com/mapbox/mapbox-gl-native/issues/1309#issuecomment-96108868 --- src/mbgl/map/tile_data.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/mbgl/map/tile_data.cpp b/src/mbgl/map/tile_data.cpp index bb8d18d12f7..80fd6346d3d 100644 --- a/src/mbgl/map/tile_data.cpp +++ b/src/mbgl/map/tile_data.cpp @@ -60,13 +60,16 @@ void TileData::cancel() { void TileData::reparse(Worker& worker, std::function callback) { util::ptr tile = shared_from_this(); worker.send( - [tile]() { - EnvironmentScope scope(tile->env, ThreadType::TileWorker, "TileWorker_" + tile->name); - tile->parse(); + [this]() { + EnvironmentScope scope(env, ThreadType::TileWorker, "TileWorker_" + name); + parse(); }, [tile, callback]() { // `tile` is bound in this lambda to ensure that if it's the last owning pointer, - // destruction happens on the map thread, not the worker thread. + // destruction happens on the map thread, not the worker thread. It is _not_ bound + // in the above lambda, because we do not want the possibility to arise that the + // after callback could execute and release the penultimate reference before the + // work callback has been destructed. callback(); }); }