From 09149e272bc675a7e33dc49c24156502d3a60b99 Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Tue, 16 Jun 2020 11:41:09 -0400 Subject: [PATCH] add ServiceWorker fix --- chromium-83-gcc-r766770.patch | 134 ++++++++++++++++++++++++++++++++++ chromium.spec | 9 ++- 2 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 chromium-83-gcc-r766770.patch diff --git a/chromium-83-gcc-r766770.patch b/chromium-83-gcc-r766770.patch new file mode 100644 index 00000000..2b63ccf4 --- /dev/null +++ b/chromium-83-gcc-r766770.patch @@ -0,0 +1,134 @@ +From bd59ce32629ef684624821419c43967b73d2989e Mon Sep 17 00:00:00 2001 +From: Hiroki Nakagawa +Date: Fri, 8 May 2020 08:25:31 +0000 +Subject: [PATCH] ServiceWorker: Avoid double destruction of + ServiceWorkerObjectHost on connection error + +This CL avoids the case where ServiceWorkerObjectHost is destroyed twice +on ServiceWorkerObjectHost::OnConnectionError() when Chromium is built +with the GCC build toolchain. + +> How does the issue happen? + +ServiceWorkerObjectHost has a cyclic reference like this: + +ServiceWorkerObjectHost + --([1] scoped_refptr)--> ServiceWorkerVersion + --([2] std::unique_ptr)--> ServiceWorkerProviderHost + --([3] std::unique_ptr)--> ServiceWorkerContainerHost + --([4] std::unique_ptr)--> ServiceWorkerObjectHost + +Note that ServiceWorkerContainerHost manages ServiceWorkerObjectHost in +map>. + +When ServiceWorkerObjectHost::OnConnectionError() is called, the +function removes the reference [4] from the map, and destroys +ServiceWorkerObjectHost. If the object host has the last reference [1] +to ServiceWorkerVersion, the destruction also cuts off the references +[2] and [3], and destroys ServiceWorkerProviderHost and +ServiceWorkerContainerHost. + +This seems to work well on the Chromium's default toolchain, but not +work on the GCC toolchain. According to the report, destruction of +ServiceWorkerContainerHost happens while the map owned by the container +host is erasing the ServiceWorkerObjectHost, and this results in crash +due to double destruction of the object host. + +I don't know the reason why this happens only on the GCC toolchain, but +I suspect the order of object destruction on std::map::erase() could be +different depending on the toolchains. + +> How does this CL fix this? + +The ideal fix is to redesign the ownership model of +ServiceWorkerVersion, but it's not feasible in the short term. + +Instead, this CL avoids destruction of ServiceWorkerObjectHost on +std::map::erase(). The new code takes the ownership of the object host +from the map first, and then erases the entry from the map. This +separates timings to erase the map entry and to destroy the object host, +so the crash should no longer happen. + +Bug: 1056598 +Change-Id: Id30654cb575bc557c42044d6f0c6f1f9bfaed613 +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2094496 +Reviewed-by: Makoto Shimazu +Commit-Queue: Hiroki Nakagawa +Cr-Commit-Position: refs/heads/master@{#766770} +--- + .../service_worker_container_host.cc | 10 +++++ + .../service_worker_object_host_unittest.cc | 38 +++++++++++++++++++ + 2 files changed, 48 insertions(+) + +--- a/content/browser/service_worker/service_worker_container_host.cc ++++ b/content/browser/service_worker/service_worker_container_host.cc +@@ -713,6 +713,16 @@ void ServiceWorkerContainerHost::RemoveS + int64_t version_id) { + DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + DCHECK(base::Contains(service_worker_object_hosts_, version_id)); ++ ++ // ServiceWorkerObjectHost to be deleted may have the last reference to ++ // ServiceWorkerVersion that indirectly owns this ServiceWorkerContainerHost. ++ // If we erase the object host directly from the map, |this| could be deleted ++ // during the map operation and may crash. To avoid the case, we take the ++ // ownership of the object host from the map first, and then erase the entry ++ // from the map. See https://crbug.com/1056598 for details. ++ std::unique_ptr to_be_deleted = ++ std::move(service_worker_object_hosts_[version_id]); ++ DCHECK(to_be_deleted); + service_worker_object_hosts_.erase(version_id); + } + +--- a/content/browser/service_worker/service_worker_object_host_unittest.cc ++++ b/content/browser/service_worker/service_worker_object_host_unittest.cc +@@ -200,6 +200,19 @@ class ServiceWorkerObjectHostTest : publ + return registration_info; + } + ++ void CallOnConnectionError(ServiceWorkerContainerHost* container_host, ++ int64_t version_id) { ++ // ServiceWorkerObjectHost has the last reference to the version. ++ ServiceWorkerObjectHost* object_host = ++ GetServiceWorkerObjectHost(container_host, version_id); ++ EXPECT_TRUE(object_host->version_->HasOneRef()); ++ ++ // Make sure that OnConnectionError induces destruction of the version and ++ // the object host. ++ object_host->receivers_.Clear(); ++ object_host->OnConnectionError(); ++ } ++ + BrowserTaskEnvironment task_environment_; + std::unique_ptr helper_; + scoped_refptr registration_; +@@ -409,5 +422,30 @@ TEST_F(ServiceWorkerObjectHostTest, Disp + events[0]->source_info_for_client->client_type); + } + ++// This is a regression test for https://crbug.com/1056598. ++TEST_F(ServiceWorkerObjectHostTest, OnConnectionError) { ++ const GURL scope("https://www.example.com/"); ++ const GURL script_url("https://www.example.com/service_worker.js"); ++ Initialize(std::make_unique(base::FilePath())); ++ SetUpRegistration(scope, script_url); ++ ++ // Create the provider host. ++ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, ++ StartServiceWorker(version_.get())); ++ ++ // Set up the case where the last reference to the version is owned by the ++ // service worker object host. ++ ServiceWorkerContainerHost* container_host = ++ version_->provider_host()->container_host(); ++ ServiceWorkerVersion* version_rawptr = version_.get(); ++ version_ = nullptr; ++ ASSERT_TRUE(version_rawptr->HasOneRef()); ++ ++ // Simulate the connection error that induces the object host destruction. ++ // This shouldn't crash. ++ CallOnConnectionError(container_host, version_rawptr->version_id()); ++ base::RunLoop().RunUntilIdle(); ++} ++ + } // namespace service_worker_object_host_unittest + } // namespace content diff --git a/chromium.spec b/chromium.spec index fd84a8f2..01834491 100644 --- a/chromium.spec +++ b/chromium.spec @@ -167,7 +167,7 @@ Name: chromium%{chromium_channel}%{nsuffix} Name: chromium%{chromium_channel} %endif Version: %{majorversion}.0.4103.97 -Release: 4%{?dist} +Release: 5%{?dist} %if %{?freeworld} %if %{?shared} # chromium-libs-media-freeworld @@ -269,6 +269,9 @@ Patch88: chromium-83-gcc-ozone-wayland.patch Patch90: chromium-83-gcc-compatibility.patch # Fix skia's handling of no_sanitize attributes to work with gcc Patch91: chromium-83.0.4103.97-skia-gcc-no_sanitize-fixes.patch +# https://chromium-review.googlesource.com/c/chromium/src/+/2094496 +# https://chromium.googlesource.com/chromium/src/+/bd59ce32629ef684624821419c43967b73d2989e +Patch92: chromium-83-gcc-r766770.patch # Use lstdc++ on EPEL7 only @@ -853,6 +856,7 @@ udev. %patch88 -p1 -b .gcc-ozone-wayland %patch90 -p1 -b .gcc-compatibility %patch91 -p1 -b .gcc-no_sanitize +%patch92 -p1 -b .gcc-r766770 # Fedora branded user agent %if 0%{?fedora} @@ -1810,6 +1814,9 @@ getent group chrome-remote-desktop >/dev/null || groupadd -r chrome-remote-deskt %changelog +* Tue Jun 16 2020 Tom Callaway - 83.0.4103.97-5 +- add ServiceWorker fix + * Mon Jun 15 2020 Tom Callaway - 83.0.4103.97-4 - use old cups handling on epel7 - fix skia attribute overrides with gcc