mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-06-15 00:15:32 +02:00
better process killing
This commit is contained in:
21
vendor/github.com/jesseduffield/kill/LICENSE
generated
vendored
Normal file
21
vendor/github.com/jesseduffield/kill/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Jesse Duffield
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
3
vendor/github.com/jesseduffield/kill/README.md
generated
vendored
Normal file
3
vendor/github.com/jesseduffield/kill/README.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Kill
|
||||
|
||||
Go package for killing processes across different platforms. Handles killing children of processes as well as the process itself.
|
33
vendor/github.com/jesseduffield/kill/kill_default_platform.go
generated
vendored
Normal file
33
vendor/github.com/jesseduffield/kill/kill_default_platform.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package kill
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Kill kills a process. If the process has Setpgid == true, then we have anticipated that it might spawn its own child processes, so we've given it a process group ID (PGID) equal to its process id (PID) and given its child processes will inherit the PGID, we can kill that group, rather than killing the process itself.
|
||||
func Kill(cmd *exec.Cmd) error {
|
||||
if cmd.Process == nil {
|
||||
// You can't kill a person with no body
|
||||
return nil
|
||||
}
|
||||
|
||||
if cmd.SysProcAttr != nil && cmd.SysProcAttr.Setpgid {
|
||||
// minus sign means we're talking about a PGID as opposed to a PID
|
||||
return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
}
|
||||
|
||||
return cmd.Process.Kill()
|
||||
}
|
||||
|
||||
// PrepareForChildren ensures that child processes of this parent process will share the same group id
|
||||
// as the parent, meaning when the call Kill on the parent process, we'll kill
|
||||
// the whole group, parent and children both. Gruesome when you think about it.
|
||||
func PrepareForChildren(cmd *exec.Cmd) {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
}
|
||||
}
|
136
vendor/github.com/jesseduffield/kill/kill_windows.go
generated
vendored
Normal file
136
vendor/github.com/jesseduffield/kill/kill_windows.go
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
// adapted from https://blog.csdn.net/fyxichen/article/details/51857864
|
||||
|
||||
package kill
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Kill kills a process, along with any child processes it may have spawned.
|
||||
func Kill(cmd *exec.Cmd) error {
|
||||
if cmd.Process == nil {
|
||||
// You can't kill a person with no body
|
||||
return nil
|
||||
}
|
||||
|
||||
pids := Getppids(uint32(cmd.Process.Pid))
|
||||
for _, pid := range pids {
|
||||
pro, err := os.FindProcess(int(pid))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
pro.Kill()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrepareForChildren ensures that child processes of this parent process will share the same group id
|
||||
// as the parent, meaning when the call Kill on the parent process, we'll kill
|
||||
// the whole group, parent and children both. Gruesome when you think about it.
|
||||
func PrepareForChildren(cmd *exec.Cmd) {
|
||||
// do nothing because on windows our Kill function handles children by default.
|
||||
}
|
||||
|
||||
const (
|
||||
MAX_PATH = 260
|
||||
TH32CS_SNAPPROCESS = 0x00000002
|
||||
)
|
||||
|
||||
type ProcessInfo struct {
|
||||
Name string
|
||||
Pid uint32
|
||||
PPid uint32
|
||||
}
|
||||
|
||||
type PROCESSENTRY32 struct {
|
||||
DwSize uint32
|
||||
CntUsage uint32
|
||||
Th32ProcessID uint32
|
||||
Th32DefaultHeapID uintptr
|
||||
Th32ModuleID uint32
|
||||
CntThreads uint32
|
||||
Th32ParentProcessID uint32
|
||||
PcPriClassBase int32
|
||||
DwFlags uint32
|
||||
SzExeFile [MAX_PATH]uint16
|
||||
}
|
||||
|
||||
type HANDLE uintptr
|
||||
|
||||
var (
|
||||
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot")
|
||||
procProcess32First = modkernel32.NewProc("Process32FirstW")
|
||||
procProcess32Next = modkernel32.NewProc("Process32NextW")
|
||||
procCloseHandle = modkernel32.NewProc("CloseHandle")
|
||||
)
|
||||
|
||||
func Getppids(pid uint32) []uint32 {
|
||||
infos, err := GetProcs()
|
||||
if err != nil {
|
||||
return []uint32{pid}
|
||||
}
|
||||
var pids []uint32 = make([]uint32, 0, len(infos))
|
||||
var index int = 0
|
||||
pids = append(pids, pid)
|
||||
|
||||
var length int = len(pids)
|
||||
for index < length {
|
||||
for _, info := range infos {
|
||||
if info.PPid == pids[index] {
|
||||
pids = append(pids, info.Pid)
|
||||
}
|
||||
}
|
||||
index += 1
|
||||
length = len(pids)
|
||||
}
|
||||
return pids
|
||||
}
|
||||
|
||||
func GetProcs() (procs []ProcessInfo, err error) {
|
||||
snap := createToolhelp32Snapshot(TH32CS_SNAPPROCESS, uint32(0))
|
||||
if snap == 0 {
|
||||
err = syscall.GetLastError()
|
||||
return
|
||||
}
|
||||
defer closeHandle(snap)
|
||||
var pe32 PROCESSENTRY32
|
||||
pe32.DwSize = uint32(unsafe.Sizeof(pe32))
|
||||
if process32First(snap, &pe32) == false {
|
||||
err = syscall.GetLastError()
|
||||
return
|
||||
}
|
||||
procs = append(procs, ProcessInfo{syscall.UTF16ToString(pe32.SzExeFile[:260]), pe32.Th32ProcessID, pe32.Th32ParentProcessID})
|
||||
for process32Next(snap, &pe32) {
|
||||
procs = append(procs, ProcessInfo{syscall.UTF16ToString(pe32.SzExeFile[:260]), pe32.Th32ProcessID, pe32.Th32ParentProcessID})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createToolhelp32Snapshot(flags, processId uint32) HANDLE {
|
||||
ret, _, _ := procCreateToolhelp32Snapshot.Call(uintptr(flags), uintptr(processId))
|
||||
if ret <= 0 {
|
||||
return HANDLE(0)
|
||||
}
|
||||
return HANDLE(ret)
|
||||
}
|
||||
|
||||
func process32First(snapshot HANDLE, pe *PROCESSENTRY32) bool {
|
||||
ret, _, _ := procProcess32First.Call(uintptr(snapshot), uintptr(unsafe.Pointer(pe)))
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func process32Next(snapshot HANDLE, pe *PROCESSENTRY32) bool {
|
||||
ret, _, _ := procProcess32Next.Call(uintptr(snapshot), uintptr(unsafe.Pointer(pe)))
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func closeHandle(object HANDLE) bool {
|
||||
ret, _, _ := procCloseHandle.Call(uintptr(object))
|
||||
return ret != 0
|
||||
}
|
Reference in New Issue
Block a user