Closed
Bug 897776
Opened 11 years ago
Closed 11 years ago
MediaRecorder infinite recursion with requestData() calls in "dataavailable" event
Categories
(Core :: Audio/Video: Recording, defect)
Tracking
()
Tracking | Status | |
---|---|---|
firefox26 | --- | fixed |
People
(Reporter: posidron, Assigned: rlin)
References
Details
(Keywords: hang, testcase, Whiteboard: [FT: Media Recording, Sprint 1])
Attachments
(3 files, 6 obsolete files)
7.25 KB,
application/x-zip-compressed
|
Details | |
3.99 KB,
patch
|
Details | Diff | Splinter Review | |
1.09 KB,
patch
|
Details | Diff | Splinter Review |
First I wasn't sure whether this is a potential bug or not but since this only re-produces with two requestData() calls inside a "dataavailable" event it lead to my believe that this is perhaps not an intended behavior.
Testcase triggers after 5 seconds.
* Call to xpconnect wrapped JSObject produced this error: *
[Exception... "'[JavaScript Error: "too much recursion" {file: "file:///Users/cdiehl/Desktop/mediarecorder-testcase.html" line: 16}]' when calling method: [nsIDOMEventListener::handleEvent]" nsresult: "0x80570021 (NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS)" location: "JS frame :: file:///Users/cdiehl/Desktop/mediarecorder-testcase.html :: <TOP_LEVEL> :: line 16" data: yes]
Reporter | ||
Comment 1•11 years ago
|
||
Reporter | ||
Updated•11 years ago
|
Attachment #780723 -
Attachment filename: mediarecorder-testcase.html → testcase
Reporter | ||
Updated•11 years ago
|
Attachment #780723 -
Attachment description: mediarecorder-testcase.html → testcase
Attachment #780723 -
Attachment filename: testcase → mediarecorder-testcase.html
Reporter | ||
Updated•11 years ago
|
Assignee | ||
Updated•11 years ago
|
Assignee: nobody → rlin
Assignee | ||
Comment 2•11 years ago
|
||
Hi Christoph,
From the API spec
void requestData()
When a MediaRecorderobject’s requestData() method is invoked, the UA must queue a task, using the DOM manipulation task source, that runs the following steps:
If state is not "recording" raise a DOM InvalidState error and terminate these steps. Otherwise:
Raise a dataavailable event containing the current Blob of saved data.
And the test case wrote:
o2.addEventListener("dataavailable", function(e) {
o2.requestData()
Should we block this behavior?
Updated•11 years ago
|
Ah. CreateAndDispatchDOMEvent does not queue a task to dispatch the event, it dispatches one synchronously. So, RequestData should use NS_NewRunnableMethod(CreateAndDispatchBlobEvent) to create a runnable and dispatch that to the main thread.
Assignee | ||
Comment 4•11 years ago
|
||
The test step will become
1. start record with initial timeslice
2. on dataavailable, also call the requestData again.
Now our implement will fire a dataavaiable event with blob size = 0 to UA,
So the UA call the request data again, then...loop forever.
Should I avoid to fire a dataavaiable event with blob size = 0 ?
No, I think we have to fire an event when requestData is called. If the dataavailable event handler calls requestData, that's not nice but we should handle it OK because we'll return to the event loop between each iteration of the dataavailable event handler.
Assignee | ||
Comment 6•11 years ago
|
||
OK,I will implement a method to prevent this problem happen.
Updated•11 years ago
|
blocking-b2g: --- → koi+
Whiteboard: [FT: Media Recording, Sprint 1]
Assignee | ||
Comment 7•11 years ago
|
||
Try to block this behavior by throwing exception.
Attachment #785661 -
Flags: feedback?(roc)
Comment 8•11 years ago
|
||
Comment on attachment 785661 [details] [diff] [review]
patch v1
Review of attachment 785661 [details] [diff] [review]:
-----------------------------------------------------------------
::: content/media/test/test_mediarecorder_avoid_recursive.html
@@ +18,5 @@
> + element.token = token;
> + manager.started(token);
> + element.test = test;
> + element.play();
> + element.onended = function () { manager.finished(token);}
Don't think this should be needed.
@@ +23,5 @@
> + element.oncanplay = function () {
> + element.mr = new MediaRecorder(element.stream);
> + element.mr.ondataavailable = function () {
> + try {
> + element.mr.requestData();
There's nothing in the test that acts as a failure condition. You should add a failure condition after requestData and finish the test gracefully in a finally block.
Assignee | ||
Comment 9•11 years ago
|
||
modify test case.
try result
https://tbpl.mozilla.org/?tree=Try&rev=f0276575385c
hit this one
147486 ERROR TEST-UNEXPECTED-FAIL | /tests/content/media/test/test_mediarecorder_reload_crash.html | Assertion count 1 is greater than expected range 0-0 assertions.
[Parent 1188] ###!!! ASSERTION: still has data in EncodedBuffers!: 'mDataSize == 0', file ../../../content/media/EncodedBufferCache.h, line 35
Can be solve by this bug 900708.
Attachment #785661 -
Attachment is obsolete: true
Attachment #785661 -
Flags: feedback?(roc)
Attachment #786163 -
Flags: feedback?(roc)
Comment 10•11 years ago
|
||
Comment on attachment 786163 [details] [diff] [review]
patch v2
Review of attachment 786163 [details] [diff] [review]:
-----------------------------------------------------------------
::: content/media/test/test_mediarecorder_avoid_recursive.html
@@ +10,5 @@
> +<pre id="test">
> +<script class="testbody" type="text/javascript">
> +var count = 0;
> +function startTest() {
> + navigator.mozGetUserMedia({audio: true, fake: true}, function(stream) {
This particular test should be able to rely on the general gMediaRecorderTest workflow to get better codec coverage.
@@ +16,5 @@
> + mediaRecorder.start();
> + mediaRecorder.ondataavailable = function () {
> + if (count++ > 100) {
> + ok(false, "shouldn't fire so many ondataavailable event!!");
> + mediaRecorder.stop();
This will result in a followup ondataavailable event firing, which will cause SimpleTest.finish to fire twice.
@@ +22,5 @@
> + } else {
> + try {
> + mediaRecorder.requestData();
> + } catch (e){
> + is(e.name, 'NS_ERROR_FAILURE', 'catch this exception, pass this test');
Why is NS_ERROR_FAILURE being used as the exception name? Couldn't we pick something more friendly?
(In reply to Robert O'Callahan (:roc) (Mozilla Corporation) from comment #5)
> No, I think we have to fire an event when requestData is called. If the
> dataavailable event handler calls requestData, that's not nice but we should
> handle it OK because we'll return to the event loop between each iteration
> of the dataavailable event handler.
I think you misunderstood what I said here. RequestData needs to dispatch the dataavailable event asynchronously. So you need to create an nsRunnable to fire the event and dispatch it to the main thread. You don't need to fire any exceptions or use this zero-blob-limit.
Assignee | ||
Comment 12•11 years ago
|
||
So if UA call the RequestData method, fire a dataavailable event, then UA call the RequestData again, could this way can avoid this recursion problem. Do the js engine has the mechanism to prevent this problem?
There's no recursion. The page calls requestData(), then returns to the event loop. Then we run the queued nsRunnable that fires dataavailable, which calls requestData() again, then we return to the event loop again. Then we carry on doing that. Not only is there no recursion, but the browser remains responsive because we can process other events on the event loop.
Assignee | ||
Comment 14•11 years ago
|
||
OK, understood. :) I will do it right away.
Assignee | ||
Comment 15•11 years ago
|
||
Works fine by this way.
Attachment #786163 -
Attachment is obsolete: true
Attachment #786163 -
Flags: feedback?(roc)
Attachment #786841 -
Flags: review?(roc)
Comment on attachment 786841 [details] [diff] [review]
patch v3
Review of attachment 786841 [details] [diff] [review]:
-----------------------------------------------------------------
Please add the test.
Attachment #786841 -
Flags: review?(roc) → review+
Assignee | ||
Comment 17•11 years ago
|
||
Should apply bug 900419 first, also test this case:
Media Recording - MediaRecorder's state is wrong when stopping media stream during recording
Attachment #780723 -
Attachment is obsolete: true
Attachment #787312 -
Flags: feedback?(jsmith)
Comment 18•11 years ago
|
||
Comment on attachment 787312 [details] [diff] [review]
test case
Review of attachment 787312 [details] [diff] [review]:
-----------------------------------------------------------------
Did you confirm this mochitest will trigger the bug without the bug fix included and fail gracefully?
Assignee | ||
Comment 19•11 years ago
|
||
Would enter timeout case.
9:35.44 TEST-UNEXPECTED-FAIL | automation.py | application timed out after 330 seconds with no output
Comment 20•11 years ago
|
||
Comment on attachment 787312 [details] [diff] [review]
test case
Review of attachment 787312 [details] [diff] [review]:
-----------------------------------------------------------------
Sounds good then. The concept of the test here looks fine.
Note - There's some cleanup needed before review.
::: content/media/test/test_mediarecorder_avoid_recursion.html
@@ +11,5 @@
> +a Bug 897776</a>
> +<pre id="test">
> +<script class="testbody" type="text/javascript">
> +function startTest() {
> + navigator.mozGetUserMedia({audio: true, fake: true}, function(stream) {
I'd suggest using the gMediaRecorder workflow here to get better codec coverage.
@@ +15,5 @@
> + navigator.mozGetUserMedia({audio: true, fake: true}, function(stream) {
> + var mediaRecorder = new MediaRecorder(stream);
> + var count = 0;
> + mediaRecorder.start();
> + mediaRecorder.ondataavailable = function (e) {
Nit on ondataavailable & onstop - fix indentation
@@ +25,5 @@
> + }
> + }
> + mediaRecorder.requestData();
> + mediaRecorder.onstop = function () {
> + ok(true, "can use this way to control the recorder object");
Can you improve the message here? Maybe something like:
'requestData within ondataavailable successfully avoided infinite recursion'
@@ +27,5 @@
> + mediaRecorder.requestData();
> + mediaRecorder.onstop = function () {
> + ok(true, "can use this way to control the recorder object");
> + SimpleTest.finish();
> + console.log("onstop");
Nit - this won't ever be executed, so this can be removed.
Attachment #787312 -
Flags: feedback?(jsmith) → feedback+
Assignee | ||
Comment 21•11 years ago
|
||
I found the media stream from audio tag isn't trigger encoder to stop recording, But fake gUM can. so I use the fake gUM to capture this bug and are debugging another one.
Attachment #787312 -
Attachment is obsolete: true
Attachment #787965 -
Flags: review?(jsmith)
Comment 22•11 years ago
|
||
(In reply to Randy Lin [:rlin] from comment #21)
> Created attachment 787965 [details] [diff] [review]
> test case v2
>
> I found the media stream from audio tag isn't trigger encoder to stop
> recording, But fake gUM can. so I use the fake gUM to capture this bug and
> are debugging another one.
Ah okay, so doing it via gMediaRecorderTests isn't possible right now due to a known bug then, right?
Updated•11 years ago
|
Attachment #787965 -
Flags: review?(jsmith) → review+
Assignee | ||
Comment 23•11 years ago
|
||
Ya, we are looking the problem which can't use the gMediaRecorderTests module to test the recorder object.
Assignee | ||
Comment 24•11 years ago
|
||
try result
https://hg.mozilla.org/try/rev/4169a8106cae
Assignee | ||
Comment 25•11 years ago
|
||
Assignee | ||
Comment 26•11 years ago
|
||
Please help to check in two patches,
try result log.
https://tbpl.mozilla.org/?tree=Try&rev=4169a8106cae
Keywords: checkin-needed
Updated•11 years ago
|
Attachment #786841 -
Attachment is obsolete: true
Updated•11 years ago
|
Attachment #787965 -
Attachment is obsolete: true
Comment 27•11 years ago
|
||
https://hg.mozilla.org/integration/b2g-inbound/rev/6bf6013084ca
https://hg.mozilla.org/integration/b2g-inbound/rev/16d14f3212fc
Flags: in-testsuite+
Keywords: checkin-needed
Comment 28•11 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/6bf6013084ca
https://hg.mozilla.org/mozilla-central/rev/16d14f3212fc
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla26
Comment 29•11 years ago
|
||
Verified per clean landing with mochitest running.
Status: RESOLVED → VERIFIED
Updated•11 years ago
|
status-firefox26:
--- → fixed
Updated•11 years ago
|
Component: Video/Audio → Video/Audio: Recording
Updated•11 years ago
|
No longer blocks: MediaRecording
You need to log in
before you can comment on or make changes to this bug.
Description
•