From 23a36caa6f6caacbc6e03cd2f86590180d6400ea Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Tue, 31 Jan 2017 17:54:34 -0800 Subject: [PATCH] Fix a race in PlatformView construction (flutter/engine#3380) The PlatformView superclass constructor was posting a task to the UI thread that adds the view to the shell's global list. This could result in UI thread operations seeing PlatformView instances that are not fully constructed and do not yet have an engine. This was happening in https://github.com/flutter/flutter/issues/7735 --- engine/src/flutter/shell/common/platform_view.cc | 12 ++++++++---- engine/src/flutter/shell/common/platform_view.h | 1 + .../shell/platform/android/platform_view_android.cc | 2 ++ .../platform/darwin/desktop/platform_view_mac.mm | 2 ++ .../shell/platform/darwin/ios/platform_view_ios.mm | 2 ++ .../shell/platform/linux/platform_view_glfw.cc | 2 ++ .../src/flutter/shell/testing/platform_view_test.cc | 1 + 7 files changed, 18 insertions(+), 4 deletions(-) diff --git a/engine/src/flutter/shell/common/platform_view.cc b/engine/src/flutter/shell/common/platform_view.cc index 644d92160c9..7f0839b1167 100644 --- a/engine/src/flutter/shell/common/platform_view.cc +++ b/engine/src/flutter/shell/common/platform_view.cc @@ -18,10 +18,7 @@ namespace shell { PlatformView::PlatformView(std::unique_ptr rasterizer) : rasterizer_(std::move(rasterizer)), size_(SkISize::Make(0, 0)), - weak_factory_(this) { - blink::Threads::UI()->PostTask( - [self = GetWeakPtr()] { Shell::Shared().AddPlatformView(self); }); -} + weak_factory_(this) {} PlatformView::~PlatformView() { blink::Threads::UI()->PostTask([] { Shell::Shared().PurgePlatformViews(); }); @@ -37,6 +34,13 @@ void PlatformView::CreateEngine() { engine_.reset(new Engine(this)); } +// Add this to the shell's list of PlatformVIews. +// Subclasses should call this after the object is fully constructed. +void PlatformView::PostAddToShellTask() { + blink::Threads::UI()->PostTask( + [self = GetWeakPtr()] { Shell::Shared().AddPlatformView(self); }); +} + void PlatformView::DispatchPlatformMessage( ftl::RefPtr message) { blink::Threads::UI()->PostTask( diff --git a/engine/src/flutter/shell/common/platform_view.h b/engine/src/flutter/shell/common/platform_view.h index 692fff9260c..5bef2e661b3 100644 --- a/engine/src/flutter/shell/common/platform_view.h +++ b/engine/src/flutter/shell/common/platform_view.h @@ -70,6 +70,7 @@ class PlatformView { explicit PlatformView(std::unique_ptr rasterizer); void CreateEngine(); + void PostAddToShellTask(); void SetupResourceContextOnIOThreadPerform( ftl::AutoResetWaitableEvent* event); diff --git a/engine/src/flutter/shell/platform/android/platform_view_android.cc b/engine/src/flutter/shell/platform/android/platform_view_android.cc index 00bcdbd29fb..67a054ce0d8 100644 --- a/engine/src/flutter/shell/platform/android/platform_view_android.cc +++ b/engine/src/flutter/shell/platform/android/platform_view_android.cc @@ -104,6 +104,8 @@ PlatformViewAndroid::PlatformViewAndroid() SetupResourceContextOnIOThread(); UpdateThreadPriorities(); + + PostAddToShellTask(); } PlatformViewAndroid::~PlatformViewAndroid() = default; diff --git a/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.mm b/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.mm index 271b4180f14..018133460a5 100644 --- a/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.mm +++ b/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.mm @@ -34,6 +34,8 @@ PlatformViewMac::PlatformViewMac(NSOpenGLView* gl_view) shell::Shell::Shared().tracing_controller().set_traces_base_path( [[paths objectAtIndex:0] UTF8String]); } + + PostAddToShellTask(); } PlatformViewMac::~PlatformViewMac() = default; diff --git a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm index b17001fd3b8..96e187f56c4 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm @@ -282,6 +282,8 @@ PlatformViewIOS::PlatformViewIOS(CAEAGLLayer* layer) NSUserDomainMask, YES); shell::Shell::Shared().tracing_controller().set_traces_base_path( [paths.firstObject UTF8String]); + + PostAddToShellTask(); } PlatformViewIOS::~PlatformViewIOS() = default; diff --git a/engine/src/flutter/shell/platform/linux/platform_view_glfw.cc b/engine/src/flutter/shell/platform/linux/platform_view_glfw.cc index aaa93016c42..5fdeb860d96 100644 --- a/engine/src/flutter/shell/platform/linux/platform_view_glfw.cc +++ b/engine/src/flutter/shell/platform/linux/platform_view_glfw.cc @@ -49,6 +49,8 @@ PlatformViewGLFW::PlatformViewGLFW() }); valid_ = true; + + PostAddToShellTask(); } PlatformViewGLFW::~PlatformViewGLFW() { diff --git a/engine/src/flutter/shell/testing/platform_view_test.cc b/engine/src/flutter/shell/testing/platform_view_test.cc index 1e5a7185672..351416a9c27 100644 --- a/engine/src/flutter/shell/testing/platform_view_test.cc +++ b/engine/src/flutter/shell/testing/platform_view_test.cc @@ -12,6 +12,7 @@ namespace shell { PlatformViewTest::PlatformViewTest() : PlatformView(std::unique_ptr(new NullRasterizer())) { CreateEngine(); + PostAddToShellTask(); } PlatformViewTest::~PlatformViewTest() = default;