Skip to content

Don't call _emscripten_futex_wake if not a function #8481

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

Merged
merged 2 commits into from
May 9, 2019

Conversation

VirtualTim
Copy link
Collaborator

This can happen if the thread throws on initialisation. Trying to call a function that doesn't exist will throw, hiding the previously caught exception.
Fixes #8446.

This can happen if the thread throws on initialisation. Trying to call a function that doesn't exist will throw, hiding the previously caught exception.
Fixes emscripten-core#8446.
@kripken
Copy link
Member

kripken commented Apr 25, 2019

How does this hide the previous exception? Both should be logged, I'd think?

I tend to think that we should not add code that tries to make things work if the thread failed to even initialize - then the entire state of the world is just bad, and nothing can be expected to work. There are any number of other possible problems in that case, I'd guess.

@VirtualTim
Copy link
Collaborator Author

So the code I modified is in a try-catch. The logic is basically:
If a thread throws,

  1. check if the exception is not "Canceled! | SimulateInfiniteLoop | pthread_exit"
  2. mark the thread as stopped,
  3. restart threads waiting on this one,
  4. then rethrow the caught error.

If restarting threads (3.) throws, then the previously caught error never gets re-thrown (4.).

The point of this isn't to try and keep things working, its to try and make sure that the error that gets bubbled up is the initial error, not Module._emscripten_futex_wake is not a function. The purpose of this is for developers, not for the end user.

Basically this is about making the thrown error the correct/original one.

@kripken
Copy link
Member

kripken commented May 1, 2019

I see. Ok, makes sense to improve the error for developers, I agree. How about doing something like this, though?

#if ASSERTIONS
  assert(..that thing is a function.., ".. error message that explains pthreads were not set up properly etc. " + original error message);
#endif

Putting it behind ASSERTIONS ensures it doesn't add overhead in general, and I think it's clearer as an assert (rather than an if that just skips something).

@VirtualTim
Copy link
Collaborator Author

Yeah I guess I can do that. I just thought overhead didn't really matter since it only reaches this check if something goes fatally wrong.

@kripken
Copy link
Member

kripken commented May 2, 2019

The overhead is minor, I agree, but I think it's also a matter of clarity - an assertion directly says what we expect to be true there.

@VirtualTim
Copy link
Collaborator Author

I guess, but you lose useful information like the stack trace. Instead you get the stack trace of the wrong exception. And in builds without ASSERTIONS defined the wrong error is still thrown.
I guess I could put an #if ASSERTIONS around that line? Would that be acceptable?

@sbc100
Copy link
Collaborator

sbc100 commented May 3, 2019

Whichever way you do it can you make you there is comment about why _emscripten_futex_wake might end up not being a function at this point in the code?

@@ -203,7 +203,9 @@ this.onmessage = function(e) {
} else {
Atomics.store(HEAPU32, (threadInfoStruct + 4 /*C_STRUCTS.pthread.threadExitCode*/ ) >> 2, (e instanceof {{{ makeAsmGlobalAccessInPthread('ExitStatus') }}}) ? e.status : -2 /*A custom entry specific to Emscripten denoting that the thread crashed.*/);
Copy link
Member

Choose a reason for hiding this comment

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

Good point about the wrong stack trace being shown.

How about this: At the top of this else body, we know that this isn't an infinite loop etc., and then we want to do some changes like these Atomics and the futex stuff. How about if before the atomics, we check if we managed to set up the thread properly, that is, move your if to up here, and put it behind ASSERTIONS. So something like

#if ASSERTIONS
    if (typeof({{{ makeAsmGlobalAccessInPthread('_emscripten_futex_wake') }}}) !== "function") {
      err("could not set up thread properly");
      throw e;
   }
#endif

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

@kripken
Copy link
Member

kripken commented May 9, 2019

Great, thanks! Sorry for the amount of time this took, but it's important to get it right.

Odd errors on CI, but I'm sure they can't be because of this, merging.

@kripken kripken merged commit 160ba89 into emscripten-core:incoming May 9, 2019
@VirtualTim VirtualTim deleted the patch-4 branch May 10, 2019 02:30
VirtualTim added a commit to VirtualTim/emscripten that referenced this pull request May 21, 2019
…pten-core#8481)

Without this PR we'dt call _emscripten_futex_wake which is not set up, and fail there, hiding the real error.
VirtualTim added a commit to VirtualTim/emscripten that referenced this pull request May 23, 2019
VirtualTim added a commit to VirtualTim/emscripten that referenced this pull request May 23, 2019
belraquib pushed a commit to belraquib/emscripten that referenced this pull request Dec 23, 2020
…pten-core#8481)

Without this PR we'dt call _emscripten_futex_wake which is not set up, and fail there, hiding the real error.
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.

When a pthread fails initialisation the wrong error is thrown
3 participants