Commit 889f6c54 authored by valenting's avatar valenting
Browse files

Bug 1870499 - Make sure ContinueDoNotifyListener is called immediately during release a=diannaS

The causes of the runnable loop are as follows:
1. In Release we have a special case to make sure OnStart&OnStop are always
   called. We do this by dispatching a runnable that calls DoNotifyListener.
2. DoNotifyListener is called, then the reference to the channel is again
   dropped. But at this point only OnStartRequest was called, and
   ContinueDoNotifyListener was added to mEventQ. That means another
   runnable would be dispatched.

While the loop was broken in the previous patch, we still want to ensure
OnStopRequest is called before the channel is released, so this patch
adds an argument to DoNotifyListener to select whether ContinueDoNotifyListener
should be called synchronously or dispatched to mEventQ.

Original Revision: https://phabricator.services.mozilla.com/D202798

Differential Revision: https://phabricator.services.mozilla.com/D204063
parent 42e6c125
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -230,7 +230,7 @@ NS_IMETHODIMP_(MozExternalRefCountType) HttpChannelChild::Release() {
    RefPtr<HttpChannelChild> channel = dont_AddRef(this);
    NS_DispatchToMainThread(NS_NewRunnableFunction(
        "~HttpChannelChild>DoNotifyListener",
        [chan = std::move(channel)] { chan->DoNotifyListener(); }));
        [chan = std::move(channel)] { chan->DoNotifyListener(false); }));
    // If NS_DispatchToMainThread failed then we're going to leak the runnable,
    // and thus the channel, so there's no need to do anything else.
    return mRefCnt;
@@ -1222,7 +1222,7 @@ void HttpChannelChild::NotifyOrReleaseListeners(nsresult rv) {
  DoNotifyListener();
}

void HttpChannelChild::DoNotifyListener() {
void HttpChannelChild::DoNotifyListener(bool aUseEventQueue) {
  LOG(("HttpChannelChild::DoNotifyListener this=%p", this));
  MOZ_ASSERT(NS_IsMainThread());

@@ -1241,10 +1241,14 @@ void HttpChannelChild::DoNotifyListener() {
  }
  StoreOnStartRequestCalled(true);

  if (aUseEventQueue) {
    mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
        this, [self = UnsafePtr<HttpChannelChild>(this)] {
          self->ContinueDoNotifyListener();
        }));
  } else {
    ContinueDoNotifyListener();
  }
}

void HttpChannelChild::ContinueDoNotifyListener() {
+3 −1
Original line number Diff line number Diff line
@@ -433,7 +433,9 @@ class HttpChannelChild final : public PHttpChannelChild,
                      const ResourceTimingStructArgs& timing);
  void Redirect3Complete();
  void DeleteSelf();
  void DoNotifyListener();
  // aUseEventQueue should only be false when called from
  // HttpChannelChild::Release to make sure OnStopRequest is called syncly.
  void DoNotifyListener(bool aUseEventQueue = true);
  void ContinueDoNotifyListener();
  void OnAfterLastPart(const nsresult& aStatus);
  void MaybeConnectToSocketProcess();