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 graceful parameter to Process#terminate #13070

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions spec/std/process_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ describe Process do
process.try(&.wait)
end

typeof(Process.new(*standing_command).terminate(graceful: false))

pending_win32 ".exists?" do
# We can't reliably check whether it ever returns false, since we can't predict
# how PIDs are used by the system, a new process might be spawned in between
Expand Down
4 changes: 2 additions & 2 deletions src/crystal/system/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ struct Crystal::System::Process
# Whether the process is still registered in the system.
# def exists? : Bool

# Asks this process to terminate gracefully.
# def terminate
# Asks this process to terminate.
# def terminate(*, graceful)

# Terminates the current process immediately.
# def self.exit(status : Int)
Expand Down
4 changes: 2 additions & 2 deletions src/crystal/system/unix/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ struct Crystal::System::Process
[email protected]? && Crystal::System::Process.exists?(@pid)
end

def terminate
Crystal::System::Process.signal(@pid, LibC::SIGTERM)
def terminate(*, graceful)
Crystal::System::Process.signal(@pid, graceful ? LibC::SIGTERM : LibC::SIGKILL)
end

def self.exit(status)
Expand Down
2 changes: 1 addition & 1 deletion src/crystal/system/wasi/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct Crystal::System::Process
raise NotImplementedError.new("Process#exists?")
end

def terminate
def terminate(*, graceful)
raise NotImplementedError.new("Process#terminate")
end

Expand Down
4 changes: 2 additions & 2 deletions src/crystal/system/win32/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ struct Crystal::System::Process
Crystal::System::Process.exists?(@pid)
end

def terminate
raise NotImplementedError.new("Process.kill")
def terminate(*, graceful)
LibC.TerminateProcess(@process_handle, 1)
end

def self.exit(status)
Expand Down
1 change: 1 addition & 0 deletions src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ lib LibC
fun GetCurrentProcessId : DWORD
fun OpenProcess(dwDesiredAccess : DWORD, bInheritHandle : BOOL, dwProcessId : DWORD) : HANDLE
fun GetExitCodeProcess(hProcess : HANDLE, lpExitCode : DWORD*) : BOOL
fun TerminateProcess(hProcess : HANDLE, uExitCode : UInt) : BOOL
fun CreateProcessW(lpApplicationName : LPWSTR, lpCommandLine : LPWSTR,
lpProcessAttributes : SECURITY_ATTRIBUTES*, lpThreadAttributes : SECURITY_ATTRIBUTES*,
bInheritHandles : BOOL, dwCreationFlags : DWORD,
Expand Down
14 changes: 11 additions & 3 deletions src/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,17 @@ class Process
@process_info.release
end

# Asks this process to terminate gracefully
def terminate : Nil
@process_info.terminate
# Asks this process to terminate.
#
# If *graceful* is true, prefers graceful termination over abrupt termination
# if supported by the system.
#
# * On Unix-like systems, this causes `Signal::TERM` to be sent to the process
# instead of `Signal::KILL`.
# * On Windows, this parameter has no effect and graceful termination is
# unavailable. The terminated process has an exit status of 1.
def terminate(*, graceful : Bool = true) : Nil
@process_info.terminate(graceful: graceful)
end

private def channel
Expand Down