-
Notifications
You must be signed in to change notification settings - Fork 54
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
Sanitize tests dealing with possible async exceptions #75
Comments
Most of our code is developed in the era before Nim 1.0. Back then, the support for destructors in the language had too many issues to make them practical to use. Nowadays, in Nim 1.0.6 they work well enough if you know where the traps are, but in the current development release of Nim (which will become Nim 1.2 in roughly 2 months from now), many of the issues are further ironed out. Our plan is to start introducing RAII idioms in the APIs that will address the exception-safety concern with the best practices known from C++. We can start doing this already in Nim 1.0.6 and wait for the improvements in Nim 1.2 |
transports and futures are |
Well I completely agree, In conclusion: |
To clarify, the destructors are perfectly usable without switching to It's true that the async code relies on ref-counted objects with non-lexically-scoped lifetimes, but this is not quite relevant to the specific issue here, which is "how do we ensure that cancellation happens unless the function completes successfully?". The answer is that we can use a sentry object that executes |
For the objects with non-deterministic lifetimes, the good news is that the destructors are now properly integrated with the GC and act as finalizers. |
issue here is that we want deterministic closing of the transport: the resource must be released before the end of the test and the future cancelled. in this particular case for example, the async callback will hold a reference to both of these - because we have a global dispatcher, there's also no way to ensure that the global dispatcher queue is cleared of callbacks without explicitly pointing it out (for example manually closing transport and clearing the future) so perhaps first we need to agree on terminology: these are de facto not destructors but finalizers that sometimes get called deterministically - that emphasizes their non-deterministic nature, and reminds the caller that it is not RAII we're talking about. |
a sentry object is again something that manually must be remembered - you can no longer use the transport as it was intended - even if you change the api to do something like in other words, what would this test look like in a world with destructors? |
@arnetheduck indeed on all points... almost sounds like you wish nim had rust standard library 😄 , we were getting close with Well I'm assuming each test must be a Another big issue (which @arnetheduck mentioned above too) with imho not so useful GC finalizers is the complete unpredictable (not deterministic) timing on their actual |
AFAIK |
This is the point IMO, as it stands we don't really have deterministic object lifetimes and we're stuck with |
since the topic of exception safety was raised, this is a school-book example of broken code - on any exception (and there are plenty of them above, even if there's no visible hint of it), this cancel and the close below will not be called - in tests this is annoying because you often get a cascade of failures as ports are not closed correctly, but more generally it's bad because of the proliferation of poor code examples that later are copy-pasted
raising exceptions in nim is very easy and convenient - looking at the outcomes in our code, handling them correctly and consistently turns out to be very hard in practice
Originally posted by @arnetheduck in https://github.com/notifications/beta/MDE4Ok5vdGlmaWNhdGlvblRocmVhZDcwNjE3NjY1Mjo3MDA4OTAw
The text was updated successfully, but these errors were encountered: