Bug 1524443 - Hold mozSpellChecker when using async IPC. r=masayuki
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Wed, 08 May 2019 13:21:55 +0000
changeset 531998 395d80953041add27448419fd58a0682b2795455
parent 531997 9f6e01596b42c2a9648dd4a74f8c0956724ebe6a
child 531999 182cddeb1d5c3da2ad98d614dca215acc362eed5
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1524443
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1524443 - Hold mozSpellChecker when using async IPC. r=masayuki When using `CheckAsync` IPC, we don't hold `mozSpellChecker`. It causes that `mozSpellChecker` may be destroyed during IPC call. The destructor of `mozSpellChecker` destroys actor of spellchecker IPC via `Send__delete__`. Although IPC rejects pending promises of async IPC during destroying actor, it cannot remove replay messages from parent process. So route error occurs. So we have to keep `mozSpellChecker` during async IPC. And we cannot convert attached test case to crashtest or mochitest since this depends on navigation and timing. So I don't add it. Differential Revision: https://phabricator.services.mozilla.com/D30347
extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.h
extensions/spellcheck/src/mozSpellChecker.cpp
--- a/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
+++ b/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
@@ -35,9 +35,25 @@ RemoteSpellcheckEngineChild::SetCurrentD
       },
       [spellChecker](ResponseRejectReason&& aReason) {
         spellChecker->mCurrentDictionary.Truncate();
         return GenericPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
                                                __func__);
       });
 }
 
+RefPtr<CheckWordPromise> RemoteSpellcheckEngineChild::CheckWords(
+    const nsTArray<nsString>& aWords) {
+  RefPtr<mozSpellChecker> kungFuDeathGrip = mOwner;
+
+  return SendCheckAsync(aWords)->Then(
+      GetMainThreadSerialEventTarget(), __func__,
+      [kungFuDeathGrip](nsTArray<bool>&& aIsMisspelled) {
+        return CheckWordPromise::CreateAndResolve(std::move(aIsMisspelled),
+                                                  __func__);
+      },
+      [kungFuDeathGrip](mozilla::ipc::ResponseRejectReason&& aReason) {
+        return CheckWordPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
+                                                 __func__);
+      });
+}
+
 }  // namespace mozilla
--- a/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.h
+++ b/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.h
@@ -17,15 +17,17 @@ class RemoteSpellcheckEngineChild
     : public mozilla::PRemoteSpellcheckEngineChild {
  public:
   explicit RemoteSpellcheckEngineChild(mozSpellChecker* aOwner);
   virtual ~RemoteSpellcheckEngineChild();
 
   RefPtr<GenericPromise> SetCurrentDictionaryFromList(
       const nsTArray<nsString>& aList);
 
+  RefPtr<CheckWordPromise> CheckWords(const nsTArray<nsString>& aWords);
+
  private:
   mozSpellChecker* mOwner;
 };
 
 }  // namespace mozilla
 
 #endif  // RemoteSpellcheckEngineChild_h_
--- a/extensions/spellcheck/src/mozSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozSpellChecker.cpp
@@ -112,26 +112,17 @@ nsresult mozSpellChecker::NextMisspelled
     selOffset = 0;
   }
   return NS_OK;
 }
 
 RefPtr<CheckWordPromise> mozSpellChecker::CheckWords(
     const nsTArray<nsString>& aWords) {
   if (XRE_IsContentProcess()) {
-    return mEngine->SendCheckAsync(aWords)->Then(
-        GetMainThreadSerialEventTarget(), __func__,
-        [](nsTArray<bool>&& aIsMisspelled) {
-          return CheckWordPromise::CreateAndResolve(std::move(aIsMisspelled),
-                                                    __func__);
-        },
-        [](mozilla::ipc::ResponseRejectReason&& aReason) {
-          return CheckWordPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
-                                                   __func__);
-        });
+    return mEngine->CheckWords(aWords);
   }
 
   nsTArray<bool> misspells;
   misspells.SetCapacity(aWords.Length());
   for (auto& word : aWords) {
     bool misspelled;
     nsresult rv = CheckWord(word, &misspelled, nullptr);
     if (NS_WARN_IF(NS_FAILED(rv))) {