Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AUDIO_WORKLET] Fix emscripten_audio_worklet_post_function_sig #23108

Merged
merged 1 commit into from
Feb 25, 2025

Conversation

mighty1231
Copy link
Contributor

@mighty1231 mighty1231 commented Dec 9, 2024

It fixes emscripten_audio_worklet_post_function_sig, which was previously not worked, and enhances test to cover all
emscripten_audio_worklet_post_function_*.

In order to fix, it changes the old term readAsmConstArgs to the new term readEmAsmArgs, due to conflict of #16449 and #18218

Background history:

  1. Audio Worklets #16449 proposed, introducing AudioWorklet earlier
  2. Factor out runEmAsmFunction. NFC #18218 proposed, renaming readAsmConstArgs to readEmAsmArgs
  3. Factor out runEmAsmFunction. NFC #18218 merged earlier
  4. Audio Worklets #16449 merged later, using the old term readAsmConstArgs

@mighty1231 mighty1231 force-pushed the audio-worklet-post-sig branch from 7f4c6b9 to 261e509 Compare February 13, 2025 09:09
@mighty1231
Copy link
Contributor Author

mighty1231 commented Feb 19, 2025

I see test job 'test-browser-chrome-wasm64-4gb' fails with test_offset_converter_pthread, which seems not related directly to this PR. Can I get some any help?

  test_offset_converter_pthread (test_browser.browser64_4gb) ... cache:INFO: �[32mgenerating system asset: symbol_lists/521c79b8fb310ffb91dc32c4132585ef16cab6fd.json... (this will be cached in "/root/cache/symbol_lists/521c79b8fb310ffb91dc32c4132585ef16cab6fd.json" for subsequent builds)�[0m
cache:INFO: �[32m - ok�[0m
[unresponsive tests: 1]
common:INFO: �[32mRestarting browser process�[0m
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 42318)
Traceback (most recent call last):
  File "/usr/lib/python3.8/socketserver.py", line 316, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python3.8/socketserver.py", line 347, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python3.8/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python3.8/http/server.py", line 647, in __init__
    super().__init__(*args, **kwargs)
  File "/usr/lib/python3.8/socketserver.py", line 747, in __init__
    self.handle()
  File "/usr/lib/python3.8/http/server.py", line 427, in handle
    self.handle_one_request()
  File "/usr/lib/python3.8/http/server.py", line 415, in handle_one_request
    method()
  File "/root/project/test/common.py", line 2186, in do_GET
    self.wfile.write(b'(wait)')
  File "/usr/lib/python3.8/socketserver.py", line 826, in write
    self._sock.sendall(b)
BrokenPipeError: [Errno 32] Broken pipe
----------------------------------------
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 42328)
Traceback (most recent call last):
  File "/usr/lib/python3.8/socketserver.py", line 316, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python3.8/socketserver.py", line 347, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python3.8/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python3.8/http/server.py", line 647, in __init__
    super().__init__(*args, **kwargs)
  File "/usr/lib/python3.8/socketserver.py", line 747, in __init__
    self.handle()
  File "/usr/lib/python3.8/http/server.py", line 427, in handle
    self.handle_one_request()
  File "/usr/lib/python3.8/http/server.py", line 415, in handle_one_request
    method()
  File "/root/project/test/common.py", line 2156, in do_GET
    self.wfile.write(b'OK')
  File "/usr/lib/python3.8/socketserver.py", line 826, in write
    self._sock.sendall(b)
BrokenPipeError: [Errno 32] Broken pipe
----------------------------------------
common:INFO: �[32mLaunching browser: ['/usr/bin/google-chrome', '--no-first-run', '-start-maximized', '--no-sandbox', '--use-gl=swiftshader', '--user-data-dir=/tmp/chrome-emscripten-profile', '--enable-experimental-web-platform-features', '--headless=new', '--remote-debugging-port=1234', '--enable-experimental-webassembly-features', '--js-flags=--experimental-wasm-stack-switching --experimental-wasm-type-reflection', '--disk-cache-dir=/dev/null', '--disk-cache-size=1', '--media-cache-size=1', '--disable-application-cache', '--incognito']�[0m
[test error (see below), automatically retrying]
Expected to find '/report_result?exit:0
' in '[no http server activity]
', diff:

@sbc100
Copy link
Collaborator

sbc100 commented Feb 19, 2025

test_offset_converter_pthread is a known flaky test

@@ -21,7 +21,7 @@ void MessageReceivedInAudioWorkletThread(int a, int b) {
printf("MessageReceivedInAudioWorkletThread: a=%d, b=%d\n", a, b);
assert(emscripten_current_thread_is_audio_worklet());
assert(a == 42 && b == 9000);
emscripten_audio_worklet_post_function_viii(EMSCRIPTEN_AUDIO_MAIN_THREAD, MessageReceivedOnMainThread, /*d=*/1, /*e=*/2, /*f=*/3);
emscripten_audio_worklet_post_function_sig(EMSCRIPTEN_AUDIO_MAIN_THREAD, (void *)MessageReceivedOnMainThread, "iii", /*d=*/1, /*e=*/2, /*f=*/3);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we not be tests both the _viii form and the _sig form?

So IIUC that emscripten_audio_worklet_post_function_sig simply does not work today and is not tested?

(That makes me wonder if its really needed as part of the API?)

Copy link
Contributor Author

@mighty1231 mighty1231 Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emscripten_audio_worklet_post_function_sig is not currently tested in the test suite, and it does not work properly at the moment. So that I changed existing test case. I could enhance the test, but I’d like to hear your thoughts on whether this version of test case is truly necessary. What do you think?

There are 2 threads for test: main and audio_worklet_thread

before this PR

  1. main --> audio_worklet_thread, calling _vii
  2. audio_worklet_thread --> main, calling _viii

after this PR

  1. main --> audio_worklet_thread, calling _vii
  2. audio_worklet_thread --> main, calling _sig

possible test case (necessary?, covering (both direction) * (_viii)

  1. main --> audio_worklet_thread, calling _vii
  2. audio_worklet_thread --> main, calling _sig
  3. main --> audio_worklet_thread, calling _sig
  4. audio_worklet_thread --> main, calling _viii

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as at least one of the _vxxx functions is tested that seems reasonable. Having coverage for all difference _vxxx functions seems even better.

Copy link
Contributor Author

@mighty1231 mighty1231 Feb 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I enhanced the test case with a new commit, referring other test case - test/wasm_worker/post_function.c. It now covers all difference _vxxx functions.

@sbc100
Copy link
Collaborator

sbc100 commented Feb 19, 2025

Can you mention the PR description the name of the function (emscripten_audio_worklet_post_function_sig) and mention that it has never worked (for the reasons you describe) and was not tested previously?

@sbc100 sbc100 changed the title Fix post function on AudioWorklet Fix emscripten_audio_worklet_post_function_sig Feb 19, 2025
@sbc100 sbc100 changed the title Fix emscripten_audio_worklet_post_function_sig [AUDIO_WORKLET] Fix emscripten_audio_worklet_post_function_sig Feb 19, 2025
@mighty1231
Copy link
Contributor Author

Can you mention the PR description the name of the function (emscripten_audio_worklet_post_function_sig) and mention that it has never worked (for the reasons you describe) and was not tested previously?

I changed the PR description.

Previously, I set PR description as same as my commit message. Now, PR description differs to my commit message. Is it OK?

+It fixes emscripten_audio_worklet_post_function_sig, which was previously not worked, and changes existing test to check it.

@mighty1231
Copy link
Contributor Author

mighty1231 commented Feb 20, 2025

test_offset_converter_pthread is a known flaky test

How about changing test_offset_converter.c as follow?

void magic_test_function(void) {
  int result = EM_ASM_INT({
    function report(x) {
      out(x);
      fetch('http://localhost:8888?stdout=' + encodeURIComponent(x));
    }
-    report('magic_test_function: input=' + $0);
-    var converted = wasmOffsetConverter.getName($0);
-    report('magic_test_function: converted=' + converted);
-    return converted == 'magic_test_function';
+    try {
+      report('magic_test_function: input=' + $0);
+      var converted = wasmOffsetConverter.getName($0);
+      report('magic_test_function: converted=' + converted);
+      return converted == 'magic_test_function';
+    } catch (e) {
+      report((e?.message ?? '(unknown message)') + ' ' + (e?.stack ?? '(unknown stack)'));
+      return false;
+    }
  }, get_pc());
  assert(result);
}

@mighty1231
Copy link
Contributor Author

mighty1231 commented Feb 20, 2025

Now test test_pthread_wait64_notify not works. Where does the number -43.357421875 comes from?

@@ -1,5 +1,8 @@
 main: creating worker
 main: entering timeout loop to wait for wasm worker to run
+(node:27876) TimeoutNegativeWarning: -43.357421875 is a negative number.
+Timeout duration was set to 1.
+(Use `node --trace-warnings ...` to show where the warning was created)
 worker_main
 Waiting on address with unexpected value should return 'not-equal'
 Waiting on address with unexpected value should return 'not-equal' also if timeout==0

(edited) It comes from libeventloop.js and n - _emscripten_get_now() seems to be negative value. Changing the js code directly gives annoying for tests with browser. TimeoutNegativeWarning seems emerged on node version >= 23. wasm64 may requires node version >= 24.

Instead changing the js code, node serves --disable-warning option on 21.3.0 fortunately.

  emscripten_set_timeout_loop: (cb, msecs, userData) => {
    function tick() {
      var t = _emscripten_get_now();
      var n = t + msecs;
      {{{ runtimeKeepalivePop() }}}
      callUserCallback(() => {
        if ({{{ makeDynCall('idp', 'cb') }}}(t, userData)) {
          // Save a little bit of code space: modern browsers should treat
          // negative setTimeout as timeout of 0
          // (https://stackoverflow.com/questions/8430966/is-calling-settimeout-with-a-negative-delay-ok) 😇
          {{{ runtimeKeepalivePush() }}}
          setTimeout(tick, n - _emscripten_get_now()); // Math.max(n - _emscripten_get_now(), 0) 😅
        }
      });
    }
    {{{ runtimeKeepalivePush() }}}
    return setTimeout(tick, 0);
  },

Changing file test_core.py

  @node_pthreads
  @no_wasm2js('https://github.com/WebAssembly/binaryen/issues/5991')
  def test_pthread_wait64_notify(self):
+    self.node_args += ['--disable-warning=TimeoutNegativeWarning']
    self.do_run_in_out_file_test('atomic/test_wait64_notify.c')

@mighty1231 mighty1231 force-pushed the audio-worklet-post-sig branch from 2386ed7 to f854ac0 Compare February 20, 2025 08:56
emscripten_audio_worklet_post_function_vdd(EMSCRIPTEN_AUDIO_MAIN_THREAD, vdd, 2.5, 3.5);
emscripten_audio_worklet_post_function_vddd(EMSCRIPTEN_AUDIO_MAIN_THREAD, vddd, 4.5, 5.5, 6.5);
emscripten_audio_worklet_post_function_sig(EMSCRIPTEN_AUDIO_MAIN_THREAD, viiiiiidddddd, "iiiiiidddddd", 10, 11, 12, 13, 14, 15, 16.5, 17.5, 18.5, 19.5, 20.5, 21.5);
emscripten_audio_worklet_post_function_v(EMSCRIPTEN_AUDIO_MAIN_THREAD, sided_test_finished);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use a different function here? e.g. do_exit? Then you don't need the testingAudioWorklet global maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. On resolving conflict with merged PR [test] AudioWorklet tests now correctly run and exit #23695, I used emscripten_force_exit(0); as the PR used, instead of do_exit.
  2. Originally, testingAudioWorklet is on the purpose to check emscripten_current_thread_is_audio_worklet() behaves correctly on each callbacks. I changed the name of it to onAudioWorkletThread, for legibility.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, it just seems a little odd that this callback has two completely different behaviors depending on the thread. Why not have two different callbacks, one which gets called on the worklet and triggers the second set of callbacks, and one which run on the main thread call on_exit which just does the exiting?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree

} else { // for the second call, finishing checks for audio worklet -> main
#ifdef REPORT_RESULT
REPORT_RESULT(success);
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just access success == XX here and return zero?

Copy link
Contributor Author

@mighty1231 mighty1231 Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

During resolving conflict, I changed emscripten_force_exit(0);, and added assertion to check callbackCount with 16=8 for main->awthread + 8 for awthread->main

@mighty1231 mighty1231 force-pushed the audio-worklet-post-sig branch 2 times, most recently from ed135ce to d6a88c2 Compare February 21, 2025 01:19
@mighty1231
Copy link
Contributor Author

mighty1231 commented Feb 21, 2025

  1. Last force pushed commit was just fixing typo, due to changing all of success to callbackCount.

    -void WebAudioWorkletThreadInitialized(EMSCRIPTEN_WEBAUDIO_T audioContext, bool callbackCount, void *userData) {
    +void WebAudioWorkletThreadInitialized(EMSCRIPTEN_WEBAUDIO_T audioContext, bool success, void *userData) {
  2. I added just experimental commit, in order to try to resolve test flakiness, but I have not changed PR title and description. Add it to PR description vs Create a new PR about flaky vs Drop experimental commit?

@sbc100
Copy link
Collaborator

sbc100 commented Feb 21, 2025

If you are able to help debug the flakiness that would be amazing, but that should part of a separate PR

@mighty1231 mighty1231 force-pushed the audio-worklet-post-sig branch from d6a88c2 to 83a866f Compare February 21, 2025 06:15
@mighty1231
Copy link
Contributor Author

If you are able to help debug the flakiness that would be amazing, but that should part of a separate PR

@sbc100 I separated PR with #23716

@mighty1231
Copy link
Contributor Author

Is test-browser.test_codesize_hello_dylink flaky?

======================================================================
FAIL [0.003s]: test_codesize_hello_dylink (test_other.other)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.8/unittest/case.py", line 60, in testPartExecutor
    yield
  File "/usr/lib/python3.8/unittest/case.py", line 676, in run
    self._callTestMethod(testMethod)
  File "/usr/lib/python3.8/unittest/case.py", line 633, in _callTestMethod
    method()
  File "/root/project/test/common.py", line 897, in resulting_test
    return func(self, *args)
  File "/root/project/test/test_other.py", line 9127, in test_codesize_hello
    self.run_codesize_test('hello_world.c', *args)
  File "/root/project/test/test_other.py", line 9017, in run_codesize_test
    self.check_expected_size_in_file('wasm', size_file, wasm_size)
  File "/root/project/test/common.py", line 1679, in check_expected_size_in_file
    self.assertLess(ratio, size_slack)
  File "/usr/lib/python3.8/unittest/case.py", line 1298, in assertLess
    self.fail(self._formatMessage(msg, standardMsg))
  File "/usr/lib/python3.8/unittest/case.py", line 753, in fail
    raise self.failureException(msg)
AssertionError: 0.15836079077429985 not less than 0.05

Is test-browser-firefox.test_wasm_worker_lock_async_acquire_minimal_runtime flaky?

  test_wasm_worker_lock_async_acquire_minimal_runtime (test_browser.browser) ... cache:INFO: �[32mgenerating system asset: symbol_lists/6b6f462a54bb66fcbe3f154a623efbd87bf62831.json... (this will be cached in "/root/cache/symbol_lists/6b6f462a54bb66fcbe3f154a623efbd87bf62831.json" for subsequent builds)�[0m
cache:INFO: �[32m - ok�[0m
[test error (see below), automatically retrying]
Expected to find '/report_result?exit:0
' in '//report_result?exception:can't access property "postMessage", U[a] is undefined / emscripten_wasm_worker_post_function_v@blob:http://localhost:8888/623e1592-52e3-4247-aca1-8ed10e372597:241:3
@blob:http://localhost:8888/623e1592-52e3-4247-aca1-8ed10e372597 line 275 > WebAssembly.instantiate:wasm-function[22]:0x854
@blob:http://localhost:8888/623e1592-52e3-4247-aca1-8ed10e372597 line 275 > WebAssembly.instantiate:wasm-function[23]:0x9ed
emscripten_lock_async_acquire/d/<@blob:http://localhost:8888/623e1592-52e3-4247-aca1-8ed10e372597:220:11
', diff:

--- expected
+++ actual
@@ -1 +1,5 @@
-/report_result?exit:0
+//report_result?exception:can't access property "postMessage", U[a] is undefined / emscripten_wasm_worker_post_function_v@blob:http://localhost:8888/623e1592-52e3-4247-aca1-8ed10e372597:241:3
+@blob:http://localhost:8888/623e1592-52e3-4247-aca1-8ed10e372597 line 275 > WebAssembly.instantiate:wasm-function[22]:0x854
+@blob:http://localhost:8888/623e1592-52e3-4247-aca1-8ed10e372597 line 275 > WebAssembly.instantiate:wasm-function[23]:0x9ed
+emscripten_lock_async_acquire/d/<@blob:http://localhost:8888/623e1592-52e3-4247-aca1-8ed10e372597:220:11
+

@cwoffenden
Copy link
Contributor

Just to say nice work, I think every function of the AW API now has code coverage with this addition and #23659.

@sbc100
Copy link
Collaborator

sbc100 commented Feb 21, 2025

The codesize test I believe just needs to be rebaselines. I'll that now.

@sbc100
Copy link
Collaborator

sbc100 commented Feb 21, 2025

Rebaselined: fc15522

It fixes emscripten_audio_worklet_post_function_sig, which was
previously not worked, and enhances test to cover all
emscripten_audio_worklet_post_function_*.

In order to fix, it changes the old term `readAsmConstArgs` to
the new term `readEmAsmArgs`, due to conflict of emscripten-core#16449 and emscripten-core#18218

Background history:

1. emscripten-core#16449 proposed, introducing AudioWorklet earlier
2. emscripten-core#18218 proposed, renaming readAsmConstArgs to readEmAsmArgs
3. emscripten-core#18218 merged earlier
4. emscripten-core#16449 merged later, using the old term `readAsmConstArgs`

enhance the test for cover all emscripten_audio_worklet_post_function_*
@mighty1231 mighty1231 force-pushed the audio-worklet-post-sig branch from 83a866f to be59a9d Compare February 25, 2025 01:33
@sbc100 sbc100 merged commit 9d0425f into emscripten-core:main Feb 25, 2025
28 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants