Skip to content

Canvas::set_target is actually unsound #657

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

Closed
Cobrand opened this issue May 13, 2017 · 1 comment
Closed

Canvas::set_target is actually unsound #657

Cobrand opened this issue May 13, 2017 · 1 comment

Comments

@Cobrand
Copy link
Member

Cobrand commented May 13, 2017

cc @nrxus

I made an article last week about our experience trying to refactor SDL2's render part, which you can see here. The article was very well, however a certain Ralf sent me an email with a very interesting statement:

However, I am slightly concerned about your with_target at the end of the post. It seems to me like this suffers from the same problem that thread::scoped already ran into, namely -- Rust does not prevent memory leaks, and as a result, the destructor is not guaranteed to run. Specifically, what happens if someone calls mem::forget(canvas.with_target(tex))? Maybe I am missing something, but it seems to me like this would leave the canvas in a bad state.

rust-lang/rust#24292
https://github.com/rust-lang/rfcs/blob/master/text/1066-safe-mem-forget.md

And he was totally right: if you mem::forget the TextureCanvas, the old canvas will render to a Texture instead of a Window... this would have been a minor problem if it was actually sound, but it isn't; now that TextureCanvas is dropped, the texture can be used freely again, including being able to render on itself (never tried, but sound like a terrible idea), and being dropped itself, leading to the texture being targeted by the Canvas internally actually being freed, but still being targeted for draws and such.

The solution here is to actually give a closure as a parameter of with_target, allowing us to control in 100% of the cases when to reset the target. The inconvenient part is that it would be more annoying to use, but it's the price to pay for safety, unfortunately.

@RalfJung
Copy link

Seems I was too slow to open this issue myself. Whatever, the fix looks good :)

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

No branches or pull requests

2 participants