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

Equivalent to Python atexit functionality #11695

Closed
bmurphy1976 opened this issue Jan 21, 2014 · 8 comments
Closed

Equivalent to Python atexit functionality #11695

bmurphy1976 opened this issue Jan 21, 2014 · 8 comments

Comments

@bmurphy1976
Copy link

I can't always guarantee that users are going to properly use a library (calling init methods, cleanup methods, etc.).

Occasionally things die horribly and you want to provide stronger guarantees about when things fail.

Is there a way to hook up to an exit signal of sorts to execute code when a program exits regardless of the exit mechanism? Something like Python atexit?

@liigo
Copy link
Contributor

liigo commented Jan 21, 2014

Drop?

2014/1/21 Bryan Murphy notifications@github.com

I can't always guarantee that users are going to properly use a library
(calling init methods, cleanup methods, etc.).

Occasionally things die horribly and you want to provide stronger
guarantees about when things fail.

Is there a way to hook up to an exit signal of sorts to execute code when
a program exits regardless of the exit mechanism? Something like Python
atexit?


Reply to this email directly or view it on GitHubhttps://github.com//issues/11695
.

by Liigo, http://blog.csdn.net/liigo/
Google+ https://plus.google.com/105597640837742873343/

@bmurphy1976
Copy link
Author

By Drop do you mean the Drop destructor trait? I've used that to set a "static mut Option<>" variable, however the Drop destructor does not run on exit and I was told on irc that this was likely going to be disallowed in the future.

@thestinger
Copy link
Contributor

An atexit handler only runs when you can a specific exit function tied to it. A user could always just run out of memory (causing an abort) or call abort themselves.

@pnkfelix
Copy link
Member

@bmurphy1976 have you considered designing your library so that one must pass around a Context struct in order to use its core methods? Then the type system would force the user to call your library's init function (since that would be how they would get their hands on a context), and you would implement the Drop trait on the context struct.

Alternatively, if you do not want to thread a context argument through your program logic, an alternative is to make the entry point of your library take a proc that it invokes for the rest of the program. In other words, a single instance of continuation-passing style (CPS), but without CPS-transforming the whole program. Then that initialization routine has a local variable at the base of the stack, and you put the impl of Drop on that, so that when the program either returns or fails, your destructor runs.

Basically I'm just describing a couple ways that you could revise your library design so that you would be able to use the Drop trait.


(As for the feature request itself, I'm ambivalent about whether to add this particular feature. If people find it useful then I will not object, but I'm not yet convinced this is dire need for it in the runtime.)

@bmurphy1976
Copy link
Author

Thanks. I've considered the context approach and I'm not a big fan of the CPS approach (for this particular problem anyway).

At the moment I'm coming from the perspective of designing a wrapper for a very common C library. Ultimately, I would want to balance "ensuring things are done right" with "the simplest/easiest to use API possible."

Asking users to pass around a context everywhere, manually clean up on exit, or use CPS passing style are all "busywork" to me. Sometimes, our users just want to call a URL and fetch a json file. All this init, teardown, cleanup, nonsense is ceremony.

Anyway, something to consider.

@dcbishop
Copy link

I'm considering this problem myself due to SDL requiring initialization of it's subsystems and needing to have sdl_Quit called at exit.

For my current approach I'm considering making a static. mutex locked reference count of objects using SDL and putting the code in the objects drop function that only runs when it's the last reference. Does require a little bit of unsafe code but other than that should work.

My main concern is whether or not SDL can be reinitialized after SDL_Quit is called (There are also functions like SDL_VideoInit and SDL_VideoQuit which could give more fine grained control over everything).

@pnkfelix
I was considering the context approach, but nothing would prevent someone creating 2 contexts and destroying one of them causing the global deinitilization stuff to fire while leaving a context that expects everything to still be initialized.

@eddyb
Copy link
Member

eddyb commented Oct 6, 2014

@dcbishop You could use an Once (or an AtomicBool) in a static mut to ensure only one context can exist at any given time.
After #17718 is fully implemented, such code could be safe, AFAIK.

As for the proposed feature, it seems similar to global destructors (which would require an RFC, but many devs are opposed to it, so I doubt it has much of a chance).
However, our TLD (task_local data) allows destructors (that run on task death, but not aborts), so that may be used instead (where thread locality is applicable/helpful).

@steveklabnik
Copy link
Member

I'm pulling a massive triage effort to get us ready for 1.0. As part of this, I'm moving stuff that's wishlist-like to the RFCs repo, as that's where major new things should get discussed/prioritized.

This issue has been moved to the RFCs repo: rust-lang/rfcs#712

dnaeon referenced this issue in dnaeon/rust-zbx Jul 28, 2015
flip1995 pushed a commit to flip1995/rust that referenced this issue Nov 2, 2023
Fix get_first false negative for VecDeque

fixes rust-lang#11695

Also run the lint on `VecDeque` and suggest using `.front()` instead of `.get(0)` when trying to access the first element.

PS: At first I implemented the VecDeque Lint in a separate `if_chain` (see the previous commit).
Let me know if thats the preferred way, then I will remove the refactoring into one block.

changelog: [`get_first`]: fix false negative: Also lint `VecDeque` and suggest using `front()`
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

7 participants