CodyC
CodyC4w ago

Reliable pattern for cleaning up resources as process exists?

I'm using Explicit Resource Management (await using resource = ...), but [Symbol.asyncDispose] doesn't get called if my program is killed with SIGINT or other signals. Is there a known/good pattern for making sure some resource gets cleaned up, even if the process is dying? I'm familiar with window.onunload, but since that's a global, it feels unreliable to rely on, since anything else in my dependencies might overwrite it during a lengthy runtime. I may also have more than one thing that I want to clean up. (never mind, unload doesn't fire during SIGINT) I also know about Deno.addSignalListener() but there are an awful lot of signals I'd need to listen to.
3 Replies
CodyC
CodyCOP4w ago
I hacked together a thing that does this in my critical path, at least: * Register signal handlers for SIGTERM and SIGINT (others I should add?) * The handler sets an "aborted" flag. * Periodically check that flag in my code (it's mostly a loop) and throw an exception if we aborted. * Unregister the event handlers at the end of my scope. ... but this only works for my example because I know my exception will bubble all the way up out of main(), so I don't lose the default ctrl-c behavior of killing the app. Doing this in a library would be bad news because the user might be trying to SIGINT (ctrl-c) to quit the program but some higher-level handling is catching the exception.
Leokuma
Leokuma4w ago
Interesting. Maybe this question is worth opening an issue. I wonder if it would be possible for the Deno runtime itself to automatically cleanup resources declared with using. Not sure if that could work, whether Deno would know the order to cleanup each using
CodyC
CodyCOP4w ago
In other languages, the process shutting down can result in exceptions being thrown, which lets the usual code pathways (finally blocks) clean up resources. I'm thinking, KeyboardInterrupt in Python, or InterruptedException in Java. But, I don't know if JS/V8 has anything like that. You'd need to be able to just throw some exception at any trivial point in code. I'd settle for something that let me register (and later remove) a "cleanup" callback that would have a chance to run as the process is exiting from a signal, an .exit(), unhandled rejection, etc. (so I don't need to track down all the cases, which may change in the future)

Did you find this page helpful?