I have an application that runs in the background, with the #[windows_subsystem = "windows"] attribute, so as not to spawn a console. However, the ctrlc crate does not detect various forms of shutdown (killed by task manager, killed because computer is shutting down.) The handler needs to write to a file to save some data for the next time it runs, and I cannot get clib's signal function to work, as somewhere between passing closures, the address of the function I want to run, or some data associated with it, is lost in translation and closes with a STATUS_ACCESS_VIOLATION.
#Creating an interrupt handler for windows
39 messages · Page 1 of 1 (latest)
Are you using any unsafe code?
in attempts to solve this I have been, but that is not part of the regular application.
I think this function only works if there is a console window
https://learn.microsoft.com/en-us/windows/console/setconsolectrlhandler
It's used by the crtrlc crate so if that's the case then it won't work without a console window 🤔
Yeah, and all the other win32 api stuff seems to imply you need either a console window or a gui window in order to detect these events.... With this program running in the background, that would defeat the purpose.
Is it an option to simply maintain the file so that you dont need shutdown logic?
It's the most robust option - there's no code you can write to handle a power loss event
Strictly speaking, no, I suppose not. Just seems like a waste to write to the file- repeatedly.
But this is just a windows desktop application and power loss isn't a concern.
What kind of workload does you app have? It's often pretty ok to use a simple debounced setup
It spends the super majority of its time idle and only actually does anything when the user hits a keyboard shortcut.
Yeah awesome, I'd say it's worth using a file each time then :)
I haven't heard the term "debounced setup" - what is that
You can debounce the code that writes out state to disk to avoid lots of writes when the user is interacting
The idea is that you say "this just changed, write out to our file in 1s" and then if any new events happen before 1s, you cancel the first write and start again
When the user stops giving you events, the 1s expires and you write to disk
Thanks! Yeah, I got so tunnel visioned on handling the signal that this solution didn't even occur to me.
So, am I to assume that if someone is using #[windows_subsystem="windows"] that you sacrifice the ability to handle interrupts?
That's not exactly right. winapi doesn't really do interrupts in the way linux does
There's just callbacks you can register with the system
and the apis accessible to any given application
And a windows_subsystem="windows" application can definitely use callback-based apis
just nothing like sigkill
I consider myself a pretty talented googler, and could not find how to setup these callbacks
Yep, I dont know any windows API for sigkill without a UI. Youre right
I just meant to add that there are interrupts for other things - if you started using an audio API, you'd have something similar to SetConsoleCtrlcHandler and WM_CLOSE
Oh, here's an interesting route!
You could register your application as a service
and the service manager will be responsible for sending you STOPPED messages
which are sent your way on shutdown (thought you're meant to be very fast about processing that message. using the disk on the main thread probably isnt appropriate, and you can't assume youll have time to successfully save state. I'd still prefer the debounced saving)
I actually do plan to register this app as a service, but frankly, if you don't have time to save to disk, why even have the handler
If a service must do lengthy processing when the service is executing the control handler, it should create a secondary thread to perform the lengthy processing, and then return from the control handler
I probably overstated that - you can certainly send a message to your worker thread, and very likely manage to write to disk
You've actually got 125 seconds
which is bound to be fine on nearly all desktop systems
If the service requires more time to clean up, it should send STOP_PENDING status messages, along with a wait hint, so the service controller knows how long to wait before reporting to the system that service shutdown is complete. However, to prevent a service from stopping shutdown, there is a limit to how long the service controller will wait. If the service is being shut down through the Services snap-in, the limit is 125 seconds.
Services can also use the SetConsoleCtrlHandler function to receive shutdown notification. This notification is received when the running applications are shutting down, which occurs before services are shut down.
Oh cool, you have even longer :)
Yeah, go for this