New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 740501 link

Starred by 7 users

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 2
Type: Bug

Blocking:
issue 738929


Participants' hotlists:
WebRTC-1.0-Spec-Compliance


Sign in to add a comment

RTCPeerConnection.onnegotiationneeded can sometimes fire multiple times in a row

Project Member Reported by hbos@chromium.org, Jul 10 2017

Issue description

RTCPeerConnection::NegotiationNeeded() should set a negotiationneeded flag to true, and only queue the event to fire if the flag went from false to true. This flag should be reset when it fires.

Currently we have no such flag, so performing multiple actions in the same task execution that require negotiation will cause multiple onnegotiationneeded events to fire (where the first one will fire at a time when all actions will be covered and the subsequent onnegotiationneeded pointless).

E.g.

pc.addStream(s1);
pc.addStream(s2);

Or

pc.addTrack(t1);
pc.addTrack(t2);
 
See also https://bugs.chromium.org/p/chromium/issues/detail?id=665200

Even though Chrome now supports addTrack(), it's not practical to use it since even rudimentary demos for audio and video will fail to negotiate: https://jsfiddle.net/jib1/yxbLvjm6/

Comment 2 by hbos@chromium.org, Jan 25 2018

Cc: hdodda@chromium.org
 Issue 665200  has been merged into this issue.

Comment 3 by hbos@chromium.org, Jan 25 2018

addTrack() works both with and without adapter.js:
https://jsfiddle.net/yxbLvjm6/19/

onnegotiationneeded does fire multiple times but that is unrelated to whether addStream or addTrack is used.

Comment 4 by hbos@chromium.org, Jan 25 2018

Tested with latest Chrome.

Comment 5 by hbos@chromium.org, Jan 25 2018

Tip of tree I mean, not stable yet.

Comment 6 by hbos@chromium.org, Feb 8 2018

Blocking: 738929

Comment 7 by hbos@chromium.org, Feb 8 2018

Labels: -Pri-3 Pri-2
Status: Started (was: Assigned)

Comment 8 by hbos@chromium.org, Feb 8 2018

Related: https://crbug.com/webrtc/7693
Project Member

Comment 9 by bugdroid1@chromium.org, Feb 9 2018

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/bd82fc5c072529638631929e7f1fe75f653b52c6

commit bd82fc5c072529638631929e7f1fe75f653b52c6
Author: Henrik Boström <hbos@chromium.org>
Date: Fri Feb 09 10:24:56 2018

Don't fire onnegotiationneeded if flag has already been reset.

Per-spec, updating the negotiation needed flag is slightly more
complicated than "= true;" and involves checking if negotiation is
needed.
https://w3c.github.io/webrtc-pc/#dfn-update-the-negotiation-needed-flag

This operation is not implemented in third_party/webrtc, so both before
and after this CL we trust that when the negotiation needed signal
reaches the main thread negotiation is still needed. This may not hold
in some obscure edge cases like rollback. This is an existing problem
not new to this CL.

This CL implements the part of the spec that says to queue a task that
fires the event and resets the flag if the flag is not already reset.
This resolves a long-lived bug where onnegotiationneeded is fired
multiple times - once per API call instead of once for each time the
flag goes from false to true.

Example:
  pc.addTrack(t1);
  pc.addTrack(t2);
  pc.onnegotiationneeded = () => {
    console.log('negotiation needed!');
  }

Before the CL, that fired twice. Now it fires once. Both tracks set the
flag and queue a task, but by the time the second task is executed the
flag has already been reset so the second event is not redundently
fired.

Bug: 740501, webrtc:7693
Change-Id: I0430d26158d50aa4d18d5f27f92a5a7bb3e68a9d
Reviewed-on: https://chromium-review.googlesource.com/908450
Commit-Queue: Henrik Boström <hbos@chromium.org>
Reviewed-by: Harald Alvestrand <hta@chromium.org>
Cr-Commit-Position: refs/heads/master@{#535681}
[modify] https://crrev.com/bd82fc5c072529638631929e7f1fe75f653b52c6/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-events.html
[modify] https://crrev.com/bd82fc5c072529638631929e7f1fe75f653b52c6/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-onnegotiationneeded-expected.txt
[modify] https://crrev.com/bd82fc5c072529638631929e7f1fe75f653b52c6/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-onnegotiationneeded.html
[modify] https://crrev.com/bd82fc5c072529638631929e7f1fe75f653b52c6/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
[modify] https://crrev.com/bd82fc5c072529638631929e7f1fe75f653b52c6/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h

Comment 10 by hbos@chromium.org, Feb 9 2018

Status: Verified (was: Started)

Comment 11 by hbos@chromium.org, Feb 15 2018

Cc: mmanchala@chromium.org hbos@chromium.org
 Issue 779917  has been merged into this issue.

Comment 12 by hbos@chromium.org, Feb 15 2018

Labels: M-66
I don't this this is resolved, ONN still fires too often in 68.0.3438.3


onn.png
65.1 KB View Download
Agree. Running the fiddle from comment 1 in 68.0.3440.0 still causes

   OperationError: Failed to set local answer sdp: Called in wrong state: kStable

Adding log statements shows it fires twice https://jsfiddle.net/yxbLvjm6/26/

negotiating...
negotiating...
OperationError: Failed to set local answer sdp: Called in wrong state: kStable
checking
...negotiated
connected
completed

Compare to Firefox:

negotiating...
...negotiated
checking
connected

Comment 15 by hbos@chromium.org, May 30 2018

I'm not sure this is a Chrome bug. I'm leaning towards bug in the code snippet or in the spec.

The onnegotiaionneeded handler in https://jsfiddle.net/yxbLvjm6/26/ is an async function. The whole function is not executed at once.
Any time you do await you allow tasks to execute, by the time the async function continues executing your code after an "await", one or more task execution cycles may have been processed. Which means if anything triggers another ONN, the event should fire. Because your async handler causes setLocalDescription and setRemoteDescription, further ONN is expected. What you end up doing it attempting to perform multiple O/A cycles in "parallel", which of course will fail.

Your code snippet is suffering from reentrancy problems. You can make sure that only one ONN is handled at a time like so https://jsfiddle.net/yxbLvjm6/29/ but not sure how safe that is in more general use cases.

jbruaroey@ Am I missing something? Shouldn't SLD/SRD trigger ONN and cause reentrancy per above? Why doesn't Firefox do that?

If ONN shouldn't fire then it is for a different reason than this bug and a new bug should be filed.

Comment 16 by fi...@appear.in, May 30 2018

https://w3c.github.io/webrtc-pc/#dfn-update-the-negotiation-needed-flag is pretty clear about this:

If connection's [[NegotiationNeeded]] slot is false, abort these steps.
Fire a simple event named negotiationneeded at connection.

What you are doing is still firing onn twice in a row as shown in the screenshot. 
This even happens in a much simpler scenario of
var pc = new RTCPeerConnection(); pc.addStream(localStream)

with a stream with two tracks or

var pc = new RTCPeerConnection();
pc.addTrack(localStream.getTracks()[0]);
pc.addTrack(localStream.getTracks()[1]);

Comment 17 by hbos@chromium.org, May 30 2018

#16: That's correct but I believe I fixed that. If
pc.addTrack(localStream.getTracks()[0]);
pc.addTrack(localStream.getTracks()[1]);
means ONN fires twice regardless of O/A cycles then that is a bug.

Comment 18 by hbos@chromium.org, May 30 2018

Oh wow it does fire twice?
https://jsfiddle.net/yxbLvjm6/30/

Comment 19 by hbos@chromium.org, May 30 2018

NextAction: 2018-06-01
Status: Untriaged (was: Verified)
Need to take another look, sounds like another regression.
Status: Assigned (was: Untriaged)
The NextAction date has arrived: 2018-06-01
a variant of this, from https://stackoverflow.com/questions/51099707/peerconnection-cannot-create-an-answer/51112783#51112783

Steps to reproduce:
1) go to https://webrtc.github.io/samples/src/content/peerconnection/munge-sdp/
2) get media, create peerconnection, create offer, set offer
3) set remotePeerConnection.onnegotiationneeded = (e) => console.log('ONN')
4) check remotePeerConnection.signalingState -- should be have-remote-offer
5) call remotePeerConnection.addStream(localStream)

As a result ONN is called twice and in have-remote-offer. Which is a no-no and breaks the mdn demo.
Note there are actually two bugs here. See https://stackoverflow.com/a/53035315/918910 which reproduces both.
Cc: ar...@chromium.org guidou@chromium.org jonasolsson@chromium.org marinaciocea@chromium.org
NextAction: ----
Owner: ----
Status: Available (was: Assigned)
#24: Thanks Jan-Ivar.

CC'ing folks; this would be a nice for one of us to fix when our hands are freed.
Cc: hta@chromium.org
Added to the hotlist; this one needs some love :)
Owner: guidou@chromium.org
Status: Assigned (was: Available)
This will have big impact. Should be low hanging fruit.
Owner: jonasolsson@chromium.org
Labels: -M-66 M-73

Sign in to add a comment