Closed Bug 1617523 Opened 4 years ago Closed 4 years ago

Crash in [@ mozilla::widget::remote_backbuffer::Client::BorrowDrawTarget]

Categories

(Core :: Graphics, defect, P2)

Unspecified
Windows 10
defect

Tracking

()

RESOLVED FIXED
mozilla75
Tracking Status
firefox-esr68 --- unaffected
firefox73 --- unaffected
firefox74 --- unaffected
firefox75 --- fixed

People

(Reporter: gsvelto, Assigned: cmartin)

References

(Regression)

Details

(Keywords: crash, regression)

Crash Data

Attachments

(1 file)

This bug is for crash report bp-da5524a3-560b-4924-90f4-14fed0200221.

Top 10 frames of crashing thread:

0 xul.dll mozilla::widget::remote_backbuffer::Client::BorrowDrawTarget widget/windows/RemoteBackbuffer.cpp:555
1 xul.dll mozilla::widget::CompositorWidgetParent::StartRemoteDrawing widget/windows/CompositorWidgetParent.cpp:82
2 xul.dll mozilla::gl::TextureImage::GetSrcTileRect gfx/gl/GLTextureImage.cpp:82
3 xul.dll mozilla::layers::BasicCompositor::BeginFrameForWindow gfx/layers/basic/BasicCompositor.cpp:899
4 xul.dll mozilla::layers::LayerManagerComposite::Render gfx/layers/composite/LayerManagerComposite.cpp:1153
5 xul.dll mozilla::layers::LayerManagerComposite::UpdateAndRender gfx/layers/composite/LayerManagerComposite.cpp:645
6 xul.dll mozilla::layers::LayerManagerComposite::EndTransaction gfx/layers/composite/LayerManagerComposite.cpp:564
7 xul.dll mozilla::layers::CompositorBridgeParent::CompositeToTarget gfx/layers/ipc/CompositorBridgeParent.cpp:1047
8 xul.dll mozilla::layers::CompositorVsyncScheduler::Composite gfx/layers/ipc/CompositorVsyncScheduler.cpp:250
9 xul.dll mozilla::detail::RunnableMethodImpl<mozilla::layers::CompositorVsyncScheduler*, void  xpcom/threads/nsThreadUtils.h:1212

New crash, first started in buildid 20200213214257. GPU-process only.

Probably caused by bug 1604412

Flags: needinfo?(cmartin)
Regressed by: 1604412
Has Regression Range: --- → yes
Priority: -- → P2

It looks like the issue is that this code allows mBackbuffer to retain a non-null value even if Initialize() or CreateRemoteFileMapping() fail. The next time it is called, it will see that it already has mBackbuffer and will just return BorrowSameBuffer to Client::BorrowDrawTarget().

void Provider::HandleBorrowRequest(BorrowResponseData* aResponseData) {
  // ...

  bool needNewBackbuffer = !mBackbuffer || (mBackbuffer->GetWidth() != width) ||
                           (mBackbuffer->GetHeight() != height);

  if (!needNewBackbuffer) {
    aResponseData->result = ResponseResult::BorrowSameBuffer;
    return;
  }

  mBackbuffer.reset();

  mBackbuffer = std::make_unique<PresentableSharedImage>();
  if (!mBackbuffer->Initialize(width, height)) {
    return;
  }

  HANDLE remoteFileMapping =
      mBackbuffer->CreateRemoteFileMapping(mTargetProcessId);
  if (!remoteFileMapping) {
    return;
  }

  aResponseData->result = ResponseResult::BorrowSuccess;
  aResponseData->width = width;
  aResponseData->height = height;
  aResponseData->fileMapping = remoteFileMapping;
}

So Client will attempt to create a DrawTarget for its current mBackbuffer, but mBackbuffer==nullptr because the first call failed:

The fix is to defer setting mBackbuffer until both Initialize() and CreateRemoteFileMapping() succeed and we can be sure the Client has had the opportunity to store the backbuffer.

This has also made me realize that the Client doesn't properly handle the case where it gets a BorrowSuccess response from the Provider, but then fails to InitializeRemote() using the info (very unlikely to happen, but technically possible).

In that case, it may keep getting BorrowSameBuffer responses from the Provider, but that response is meaningless if the Client was never able to initialize the buffer in the first place.

I have added a new message to explicitly say that buffer re-use is allowed. Otherwise, Provider will always assume that a new buffer is needed.

Assignee: nobody → cmartin
Flags: needinfo?(cmartin)

This crash was caused because there was a case where the Provider would
store the SharedImage even if it failed to initialize it or send it to the
Client.

When the Client next requested a borrow, the Provider would see it was
already storing a SharedImage and would tell the Client to just
reuse the one it already had.

Since the Client never actually received it, it would end up dereferencing
a null pointer.

The fix for this is to wait until the SharedImage is fully initialized and
shared with the Client before storing it. That way, we know that if we have
it then so does the Client.

Pushed by cmartin@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/992f5734eb4e
Ensure remote backbuffer only reused if initialized properly r=jrmuizel
Status: NEW → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla75
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: