Skip to content

Commit 331ff4b

Browse files
committed
test
1 parent 597511e commit 331ff4b

File tree

4 files changed

+102
-24
lines changed

4 files changed

+102
-24
lines changed

.github/workflows/release.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ jobs:
7777
id: get_version
7878
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
7979

80+
- name: Clean artifacts directory
81+
run: rm -rf ./artifacts
82+
8083
- name: Download all artifacts
8184
uses: actions/download-artifact@v4
8285
with:

main.go

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"strconv"
2020
"strings"
2121
"sync"
22-
"syscall"
2322
"time"
2423
)
2524

@@ -479,8 +478,8 @@ func runServer(jarPath, memory string) error {
479478

480479
cmd := exec.CommandContext(ctx, "java", fmt.Sprintf("-Xmx%s", memory), "-jar", jarPath, "nogui")
481480

482-
// Place the child in its own process group so we can signal it (and its children) reliably
483-
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
481+
// Place the child in its own process group (POSIX) or leave default on Windows
482+
setCmdSysProcAttr(cmd)
484483

485484
// Wire stdout/stderr directly
486485
cmd.Stdout = os.Stdout
@@ -508,7 +507,8 @@ func runServer(jarPath, memory string) error {
508507

509508
// Signal handling: gracefully stop, then escalate
510509
sigCh := make(chan os.Signal, 4)
511-
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
510+
// Listen for interrupts and termination signals (SIGTERM on POSIX)
511+
signal.Notify(sigCh, os.Interrupt)
512512
defer signal.Stop(sigCh)
513513

514514
stopping := false
@@ -533,39 +533,25 @@ func runServer(jarPath, memory string) error {
533533
// After grace period, escalate only once
534534
select {
535535
case <-escalateOnce:
536-
go func(pid int) {
536+
go func() {
537537
t := time.NewTimer(10 * time.Second)
538538
<-t.C
539-
_ = syscall.Kill(-pid, syscall.SIGTERM)
540-
t2 := time.NewTimer(5 * time.Second)
541-
<-t2.C
542-
_ = syscall.Kill(-pid, syscall.SIGKILL)
543-
}(cmd.Process.Pid)
539+
escalateTerminate(cmd)
540+
}()
544541
default:
545542
}
546543
continue
547544
}
548-
// Already stopping: forward the signal to the child process group immediately
549-
_ = syscall.Kill(-cmd.Process.Pid, signalToSys(sig))
545+
// Already stopping: forward the signal to the child
546+
forwardSignal(cmd, sig)
550547
if interrupts >= 3 {
551548
// Hard kill on repeated interrupts
552-
_ = syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
549+
forceKill(cmd)
553550
}
554551
}
555552
}
556553
}
557554

558-
func signalToSys(sig os.Signal) syscall.Signal {
559-
switch sig {
560-
case os.Interrupt:
561-
return syscall.SIGINT
562-
case syscall.SIGTERM:
563-
return syscall.SIGTERM
564-
default:
565-
return syscall.SIGINT
566-
}
567-
}
568-
569555
func acceptEula() error {
570556
eulaContent := "# Minecraft EULA\n# Auto-accepted by mc utility\neula=true\n"
571557
return os.WriteFile("eula.txt", []byte(eulaContent), 0644)

proc_posix.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//go:build !windows
2+
3+
package main
4+
5+
import (
6+
"os"
7+
"os/exec"
8+
"syscall"
9+
"time"
10+
)
11+
12+
// setCmdSysProcAttr places the child into its own process group on POSIX systems
13+
func setCmdSysProcAttr(cmd *exec.Cmd) {
14+
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
15+
}
16+
17+
// forwardSignal forwards signals to the child's process group
18+
func forwardSignal(cmd *exec.Cmd, sig os.Signal) {
19+
if cmd == nil || cmd.Process == nil {
20+
return
21+
}
22+
_ = syscall.Kill(-cmd.Process.Pid, signalToSys(sig))
23+
}
24+
25+
// escalateTerminate tries SIGTERM then SIGKILL after a short delay
26+
func escalateTerminate(cmd *exec.Cmd) {
27+
if cmd == nil || cmd.Process == nil {
28+
return
29+
}
30+
pid := cmd.Process.Pid
31+
_ = syscall.Kill(-pid, syscall.SIGTERM)
32+
t2 := time.NewTimer(5 * time.Second)
33+
<-t2.C
34+
_ = syscall.Kill(-pid, syscall.SIGKILL)
35+
}
36+
37+
// forceKill immediately terminates the process group
38+
func forceKill(cmd *exec.Cmd) {
39+
if cmd == nil || cmd.Process == nil {
40+
return
41+
}
42+
_ = syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
43+
}
44+
45+
func signalToSys(sig os.Signal) syscall.Signal {
46+
switch s := sig.(type) {
47+
case syscall.Signal:
48+
return s
49+
default:
50+
return syscall.SIGINT
51+
}
52+
}

proc_windows.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//go:build windows
2+
3+
package main
4+
5+
import (
6+
"os"
7+
"os/exec"
8+
"time"
9+
)
10+
11+
// setCmdSysProcAttr leaves defaults on Windows; no Setpgid available
12+
func setCmdSysProcAttr(cmd *exec.Cmd) {
13+
// Optionally, set CreationFlags for new process group or console, but keep default for compatibility
14+
// cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP}
15+
}
16+
17+
// forwardSignal is a no-op on Windows; best-effort termination is handled via forceKill
18+
func forwardSignal(cmd *exec.Cmd, sig os.Signal) {
19+
// No portable signal forwarding on Windows
20+
}
21+
22+
// escalateTerminate performs a best-effort immediate kill of the child process
23+
func escalateTerminate(cmd *exec.Cmd) {
24+
if cmd == nil || cmd.Process == nil {
25+
return
26+
}
27+
time.Sleep(3 * time.Second)
28+
_ = cmd.Process.Kill()
29+
}
30+
31+
// forceKill immediately kills the process on Windows
32+
func forceKill(cmd *exec.Cmd) {
33+
if cmd == nil || cmd.Process == nil {
34+
return
35+
}
36+
_ = cmd.Process.Kill()
37+
}

0 commit comments

Comments
 (0)