-
Notifications
You must be signed in to change notification settings - Fork 173
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
Improve usability of assert/abort #175
Comments
I disagree that the VM instance an abort is associated with can be determined simply using thread locals. There's no reason why, for example, a JNI method couldn't create a new VM in the same process and thread and use it to complete its work. Trying to override and restore thread locals at every VM entry and exit point seems like at least as much work (and much harder to debug) as just passing the aborter to any code that needs it. I think we should avoid "hidden" arguments passed via the execution environment (which is what a thread local is). It hides data flow dependencies and impedes readability. |
I disagree; code to enter/exit a VM context is very localized. Code that operates within a VM context is everywhere. So instead of having the complexity in one file, we get to feel it everywhere. I'd be happy to do the legwork in demonstrating that we can catch all the enter/exit cases without adding undue complexity or maintenance burden. To be clear, I think passing a Thread* context around works fine when you're doing stuff in a very monolithic style, where you probably already have some sort of a context object everywhere you could possibly need it. This isn't the case in more separate, modular, utility classes. |
@dicej, what would you say to replacing just our assert (not expect or abort) with the standard assert (from C's |
I'd have two concerns about that:
I'd really rather see us pass an Aborter to any code that might want it, or else have that code return an error (or throw an exception) to the calling code which has the option of aborting or recovering somehow. |
The first point is easy. Funny how I just introduced a function like that :). When I'm debugging, I specifically don't want anything catching an assert except for my debugger - as soon as it's left the relevant frame, we've lost valuable context (yes, you could set a breakpoint at some strategic location - but that's a pain). Perhaps that's a good differentiator between expect and abort; we could declare that expect always throws a VMError (which has some small chance of popping up in production), and assert is for problems we shouldn't ever see outside of development. We should use expect for checking any and all low-frequency interfaces between big components, and assert elsewhere. These big component interfaces should always have the proper context for an expect anyway, so assert->expect conversion shouldn't be a problem. |
The current requirement to have a System instance in order to call abort on makes it very difficult to write "clean", modular utilities. Anything that could possibly want to assert needs to have either an Aborter (of which System is the only current implementation) or a System parameter. If we want to add an assert somewhere that we don't have one of those, we need to add such a parameter.
Let's make the choice of abort functionality a link-time option rather than a runtime option.
We make sure to include our abort function (which I've called "crash" in #171) in a separate .cpp file from most everything else. Anyone wanting to swap out the implementation can do so at compile time. We can even build a library that has that symbol undefined and expects the executable itself to define it.
The only thing we lose in that case is the context of which VM instance this abort is associated with - and that can be solved pretty simply with thread locals.
The text was updated successfully, but these errors were encountered: