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

Add Process.on_terminate #13694

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
e153e8e
pass details on interrupt
stakach Jul 22, 2023
2ad9331
fix win32 handler def
stakach Jul 22, 2023
006ce08
update public interface
stakach Jul 22, 2023
4ef574f
fix windows build
stakach Jul 23, 2023
0fa95aa
add missed windows constants
stakach Jul 23, 2023
7f54152
Merge branch 'master' into improve-process-on_interrupt
stakach Aug 18, 2023
cbd80e9
Merge branch 'master' into improve-process-on_interrupt
stakach Aug 19, 2023
78c27f1
Merge branch 'master' into improve-process-on_interrupt
stakach Aug 22, 2023
1ed9f63
Merge branch 'master' into improve-process-on_interrupt
stakach Sep 13, 2023
f9a6263
Merge branch 'master' into improve-process-on_interrupt
stakach Sep 17, 2023
2044e94
use Process::ExitReason enum
stakach Sep 18, 2023
360a3b5
remove alias
stakach Sep 18, 2023
2533fad
fix windows class vars
stakach Sep 19, 2023
6d94721
Merge branch 'master' into improve-process-on_interrupt
stakach Sep 22, 2023
0604bd2
Merge branch 'master' into improve-process-on_interrupt
stakach Nov 2, 2023
8e43767
Merge branch 'master' into improve-process-on_interrupt
stakach Nov 13, 2023
ee8f672
Merge branch 'master' into improve-process-on_interrupt
stakach Nov 16, 2023
0ea6ecb
win32 backwards compat
stakach Nov 16, 2023
118baff
remove type requirements
stakach Nov 16, 2023
793f0a6
fix wasi compatibility
stakach Nov 16, 2023
5765c73
unix with compatibility
stakach Nov 16, 2023
2352065
fix compilation
stakach Nov 16, 2023
33c9ac6
improve readability of win32 proc type
stakach Nov 16, 2023
0a11eb5
Update src/process.cr
stakach Nov 16, 2023
bdc8541
Update src/process/status.cr
stakach Nov 16, 2023
a2bc368
Update src/process/status.cr
stakach Nov 16, 2023
6bcf166
fix win32 compilation
stakach Nov 16, 2023
d497f08
minor performance improvement
stakach Nov 16, 2023
721444e
Merge branch 'master' into improve-process-on_interrupt
stakach Dec 1, 2023
38c8b51
Merge branch 'master' into improve-process-on_interrupt
stakach Dec 20, 2023
f81bb9b
Merge branch 'master' into improve-process-on_interrupt
stakach Dec 23, 2023
56115e0
Merge branch 'master' into improve-process-on_interrupt
stakach Jan 10, 2024
22a9b34
Merge branch 'master' into improve-process-on_interrupt
stakach Jan 22, 2024
78e8047
deprecate on_interrupt and use on_terminate
stakach Jan 23, 2024
d70ee33
fix call to on_terminate
stakach Jan 23, 2024
f460d5c
fix win32
stakach Jan 23, 2024
a740d4a
improve win32 on_terminate
stakach Jan 23, 2024
757079b
update docs
stakach Jan 23, 2024
79cbc17
change wording in description
stakach Jan 24, 2024
bc66bdb
add example code
stakach Jan 24, 2024
2b91b7d
crystal tool format
stakach Jan 24, 2024
fc279c4
Merge branch 'master' into improve-process-on_interrupt
stakach Jan 30, 2024
79c848d
Merge branch 'master' into improve-process-on_interrupt
stakach Jan 30, 2024
35471c9
Merge branch 'master' into improve-process-on_interrupt
stakach Feb 2, 2024
962d654
fix comments and specs for new enum values
stakach Feb 3, 2024
3ceb646
Merge branch 'master' into improve-process-on_interrupt
stakach Feb 4, 2024
8972255
Merge branch 'master' into improve-process-on_interrupt
stakach Feb 6, 2024
539b998
Merge branch 'master' into improve-process-on_interrupt
stakach Feb 8, 2024
0319fc3
Merge branch 'master' into improve-process-on_interrupt
stakach Feb 9, 2024
66b4ce0
Merge branch 'master' into improve-process-on_interrupt
stakach Feb 12, 2024
f4a3374
Merge branch 'master' into improve-process-on_interrupt
stakach Feb 26, 2024
bfdef38
Merge branch 'master' into improve-process-on_interrupt
stakach Feb 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/crystal/system/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ struct Crystal::System::Process

# Changes the root directory for the current process.
# def self.chroot(path : String)

enum Interrupt
# sigint, ctrl-c or ctrl-break events
USER_SIGNALLED
# sighup or closed event
TERMINAL_DISCONNECTED
# sigterm, logoff or shutdown events
SESSION_ENDED
end
end

module Crystal::System
Expand Down
24 changes: 22 additions & 2 deletions src/crystal/system/unix/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,28 @@ struct Crystal::System::Process
raise RuntimeError.from_errno("kill") if ret < 0
end

def self.on_interrupt(&handler : ->) : Nil
::Signal::INT.trap { |_signal| handler.call }
def self.on_interrupt(&handler : Interrupt ->) : Nil
sig_handler = Proc(::Signal, Nil).new do |signal|
int_type = case signal
when .int?
Interrupt::USER_SIGNALLED
when .hup?
Interrupt::TERMINAL_DISCONNECTED
when .term?
Interrupt::SESSION_ENDED
else
Interrupt::USER_SIGNALLED
end
handler.call int_type

# ignore prevents system defaults and clears registered interrupts
# hence we need to re-register
signal.ignore
Process.on_interrupt &handler
end
::Signal::INT.trap &sig_handler
::Signal::HUP.trap &sig_handler
::Signal::TERM.trap &sig_handler
end

def self.ignore_interrupts! : Nil
Expand Down
19 changes: 15 additions & 4 deletions src/crystal/system/win32/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ struct Crystal::System::Process
@thread_id : LibC::DWORD
@process_handle : LibC::HANDLE

@@interrupt_handler : Proc(Nil)?
@@interrupt_handler : Proc(Interrupt, Nil)?
@@interrupt_count = Crystal::AtomicSemaphore.new
@@win32_interrupt_handler : LibC::PHANDLER_ROUTINE?
@@setup_interrupt_handler = Atomic::Flag.new
@@last_interrupt = Interrupt::USER_SIGNALLED

def initialize(process_info)
@pid = process_info.dwProcessId
Expand Down Expand Up @@ -100,10 +101,19 @@ struct Crystal::System::Process
raise NotImplementedError.new("Process.signal")
end

def self.on_interrupt(&@@interrupt_handler : ->) : Nil
def self.on_interrupt(&@@interrupt_handler : Interrupt ->) : Nil
restore_interrupts!
@@win32_interrupt_handler = handler = LibC::PHANDLER_ROUTINE.new do |event_type|
next 0 unless event_type.in?(LibC::CTRL_C_EVENT, LibC::CTRL_BREAK_EVENT)
@@last_interrupt = case event_type
when LibC::CTRL_C_EVENT, LibC::CTRL_BREAK_EVENT
Interrupt::USER_SIGNALLED
when LibC::CTRL_CLOSE_EVENT
Interrupt::TERMINAL_DISCONNECTED
when LibC::CTRL_LOGOFF_EVENT, LibC::CTRL_SHUTDOWN_EVENT
Interrupt::SESSION_ENDED
else
next 0
end
@@interrupt_count.signal
1
end
Expand Down Expand Up @@ -136,8 +146,9 @@ struct Crystal::System::Process

if handler = @@interrupt_handler
non_nil_handler = handler # if handler is closured it will also have the Nil type
int_type = @@last_interrupt
spawn do
non_nil_handler.call
non_nil_handler.call int_type
rescue ex
ex.inspect_with_backtrace(STDERR)
STDERR.puts("FATAL: uncaught exception while processing interrupt handler, exiting")
Expand Down
7 changes: 5 additions & 2 deletions src/lib_c/x86_64-windows-msvc/c/consoleapi.cr
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ lib LibC
fun GetConsoleCP : DWORD
fun GetConsoleOutputCP : DWORD

CTRL_C_EVENT = 0
CTRL_BREAK_EVENT = 1
CTRL_C_EVENT = 0
CTRL_BREAK_EVENT = 1
CTRL_CLOSE_EVENT = 2
CTRL_LOGOFF_EVENT = 5
CTRL_SHUTDOWN_EVENT = 6

alias PHANDLER_ROUTINE = DWORD -> BOOL

Expand Down
11 changes: 7 additions & 4 deletions src/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,18 @@ class Process
Crystal::System::Process.signal(pid, signal.value)
end

alias Interrupt = Crystal::System::Process::Interrupt
stakach marked this conversation as resolved.
Show resolved Hide resolved

# Installs *handler* as the new handler for interrupt requests. Removes any
# previously set interrupt handler.
#
# The handler is executed on a fresh fiber every time an interrupt occurs.
#
# * On Unix-like systems, this traps `SIGINT`.
# * On Windows, this captures <kbd>Ctrl</kbd> + <kbd>C</kbd> and
# <kbd>Ctrl</kbd> + <kbd>Break</kbd> signals sent to a console application.
def self.on_interrupt(&handler : ->) : Nil
# * On Unix-like systems, this traps `SIGINT`, `SIGHUP`, `SIGTERM`.
# * On Windows, this captures <kbd>Ctrl</kbd> + <kbd>C</kbd>,
# <kbd>Ctrl</kbd> + <kbd>Break</kbd>, terminal close, windows logoff
# and shutdown signals sent to a console application.
stakach marked this conversation as resolved.
Show resolved Hide resolved
stakach marked this conversation as resolved.
Show resolved Hide resolved
def self.on_interrupt(&handler : Interrupt ->) : Nil
stakach marked this conversation as resolved.
Show resolved Hide resolved
Crystal::System::Process.on_interrupt(&handler)
end

Expand Down