Nothing Special   »   [go: up one dir, main page]

Closed Bug 1917242 Opened 11 days ago Closed 5 days ago

Chained MozPromise objects may destroy callbacks in wrong order

Categories

(Core :: XPCOM, defect, P2)

defect

Tracking

()

RESOLVED FIXED
132 Branch
Tracking Status
firefox-esr115 --- wontfix
firefox-esr128 --- affected
firefox130 --- wontfix
firefox131 --- affected
firefox132 --- fixed

People

(Reporter: janv, Assigned: janv, NeedInfo)

References

(Regression)

Details

(Keywords: regression)

Attachments

(2 files)

https://searchfox.org/mozilla-central/rev/cc01f11adfacca9cd44a75fd140d2fdd8f9a48d4/xpcom/threads/MozPromise.h#850-872

    void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
      // Note: The usage of InvokeCallbackMethod here requires that
      // ResolveFunction/RejectFunction are capture-lambdas (i.e. anonymous
      // classes with ::operator()), since it allows us to share code more
      // easily. We could fix this if need be, though it's quite easy to work
      // around by just capturing something.
      if (aValue.IsResolve()) {
        InvokeCallbackMethod<SupportChaining>(
            mResolveFunction.ptr(), &ResolveFunction::operator(),
            MaybeMove(aValue.ResolveValue()), std::move(mCompletionPromise));
      } else {
        InvokeCallbackMethod<SupportChaining>(
            mRejectFunction.ptr(), &RejectFunction::operator(),
            MaybeMove(aValue.RejectValue()), std::move(mCompletionPromise));
      }

      // Destroy callbacks after invocation so that any references in closures
      // are released predictably on the dispatch thread. Otherwise, they would
      // be released on whatever thread last drops its reference to the
      // ThenValue, which may or may not be ok.
      mResolveFunction.reset();
      mRejectFunction.reset();
    }

The problem is that mResolveFunction and mRejectFunction are actually not destroyed right after invocation, they are destroyed after invocation and chaining completion promise https://searchfox.org/mozilla-central/rev/cc01f11adfacca9cd44a75fd140d2fdd8f9a48d4/xpcom/threads/MozPromise.h#662-672
If the current thread is suspended after calling ChainTo which can call Dispatch https://searchfox.org/mozilla-central/rev/cc01f11adfacca9cd44a75fd140d2fdd8f9a48d4/xpcom/threads/MozPromise.h#590
and if other threads processing next tasks are fast enough, callbacks may end up being destroyed in wrong order.

I'll submit a gtest which demonstrates the problem.

This is blocking bug 1917169 which blocks bug 1913679 and eventually bug 1671932.

We had a similar problem in bug 1892875 for which we added mozilla::dom::quota::RunAfterProcessingCurrentEvent in bug 1901745.

Investigation of this problem started when I was testing patches for OPFS:
https://treeherder.mozilla.org/logviewer?job_id=472923301&repo=try&lineNumber=1870

OPFS has two quite complex promise chains:
https://searchfox.org/mozilla-central/rev/cc01f11adfacca9cd44a75fd140d2fdd8f9a48d4/dom/fs/parent/datamodel/FileSystemDataManager.cpp#526-674

It turns out that Android is good at slowing down/suspending one thread while allowing other threads to proceed very fast.
So https://searchfox.org/mozilla-central/rev/cc01f11adfacca9cd44a75fd140d2fdd8f9a48d4/dom/fs/parent/datamodel/FileSystemDataManager.cpp#549 can be released only after all other captures are released. The last release of the manager then happens on the QM IO thread (but it should be done on the PBackground thread).

I think I found a changeset which regressed this https://hg.mozilla.org/mozilla-central/rev/3297397ead64

Keywords: regression
Regressed by: 1367679

Set release status flags based on info from the regressing bug 1367679

Pushed by jvarga@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/25f901c0c28e
Add a gtest for expected callback destruction order; r=xpcom-reviewers,nika
https://hg.mozilla.org/integration/autoland/rev/cede0737b371
Destroy callbacks before chaining completion promise; r=xpcom-reviewers,nika
Status: ASSIGNED → RESOLVED
Closed: 5 days ago
Resolution: --- → FIXED
Target Milestone: --- → 132 Branch

The patch landed in nightly and beta is affected.
:janv, is this bug important enough to require an uplift?

  • If yes, please nominate the patch for beta approval.
  • If no, please set status-firefox131 to wontfix.

For more information, please visit BugBot documentation.

Flags: needinfo?(jvarga)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: