-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add Process.on_interrupt
#13034
Add Process.on_interrupt
#13034
Conversation
{% if flag?(:win32) %} | ||
Crystal::System::Process.start_interrupt_loop | ||
{% else %} | ||
Signal.setup_default_handlers | ||
{% end %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose these handlers could also be placed in a portable interface? But this can be added later.
# NOTE: `Process.on_interrupt` is preferred over `Signal::INT.trap`, as the | ||
# former also works on Windows. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can leave it out of the scope of this PR, but would it be feasible to implement Signal::INT.trap
as Process.on_interrupt
on Windows?
Co-authored-by: Johannes Müller <straightshoota@gmail.com>
Resolves #12224. The "interrupt" corresponds to Ctrl+C and Ctrl+Break for Windows console applications. The following will now work:
It also means that specs will abort gracefully when interrupted, whether from a spec executable or via
crystal spec
.The following does not work:
Additionally, the
bin\crystal.bat
andbin\crystal.ps1
wrappers do not use some kind ofexec
(PowerShell 7.3 addedSwitch-Process
but it is unavailable on Windows itself!), so if a custom interrupt handler returns normally without exiting the process, control returns to the console but the process will continue running in the background. This isn't a problem forcrystal spec
as specs are run inside anat_exit
.On Windows, this interrupt handler is run on a fresh thread every time an interrupt arrives, so some form of synchronization is required. Originally the plan was to integrate this into the event loop, but the current implementation uses an atomic counter instead, and the listener loop fiber on the main thread simply polls for any outstanding interrupts every 50 milliseconds. This seems to be a good compromise because e.g.
IO::FileDescriptor#flock_*
does the same thing.