fix: iris now reloads via signal handoff

This commit is contained in:
verse91
2026-04-11 22:12:15 +07:00
parent 78e19199b0
commit bed9c98747
2 changed files with 23 additions and 42 deletions
+1
View File
@@ -15,6 +15,7 @@ run:
[linux, macos]
reload:
@go build -o iris main.go
@if [ -n "${IRIS_PID:-}" ]; then kill -USR1 $IRIS_PID; fi
@if [ -z "${IRIS_FD:-}" ]; then ./iris; fi
# update pkg
+22 -42
View File
@@ -14,13 +14,13 @@ import (
"github.com/creack/pty"
"github.com/spf13/cobra"
"github.com/versenilvis/iris/commands/core"
_ "github.com/versenilvis/iris/commands/dev"
_ "github.com/versenilvis/iris/commands/fs"
_ "github.com/versenilvis/iris/commands/info"
_ "github.com/versenilvis/iris/commands/runner"
_ "github.com/versenilvis/iris/commands/search"
_ "github.com/versenilvis/iris/commands/view"
"github.com/versenilvis/iris/commands/core"
"github.com/versenilvis/iris/integration"
"golang.org/x/term"
)
@@ -36,44 +36,17 @@ It works exactly like coding editor suggestion menu drop down.`,
}
func Execute() {
go watchSelf()
if os.Getenv("IRIS_RELOADED") == "true" {
fmt.Printf("\r\n\033[35m[IRIS] reloading...\033[0m\r\n")
os.Unsetenv("IRIS_RELOADED")
}
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func watchSelf() {
exe, err := os.Executable()
if err != nil {
return
}
startTime := time.Now()
for {
time.Sleep(500 * time.Millisecond)
info, err := os.Stat(exe)
if err != nil {
continue
}
if info.ModTime().After(startTime) {
// clean up terminal before exec
fmt.Printf("\r\n\033[35m[IRIS] binary updated, reloading...\033[0m\r\n")
// we need to be careful about raw mode but syscall.Exec will replace the process
// which is fine as the new iris will setup its own raw mode
// however, to be safe for the terminal state, we'd ideally restore then exec
// but since we're inside a PTY wrapper, it's more complex
// the simplest way: just exec, the new iris will handle the terminal
err := syscall.Exec(exe, os.Args, os.Environ())
if err != nil {
fmt.Printf("Reload failed: %v\n", err)
}
}
}
}
func runWrapper() {
r, w, err := os.Pipe()
if err != nil {
@@ -86,7 +59,7 @@ func runWrapper() {
// fd 0, 1, 2 are stdin, stdout, stderr (handled by pty)
// fd 3 is our write pipe
c.ExtraFiles = []*os.File{w}
c.Env = append(os.Environ(), "IRIS_FD=3")
c.Env = append(os.Environ(), "IRIS_FD=3", fmt.Sprintf("IRIS_PID=%d", os.Getpid()))
ptmx, err := pty.Start(c)
if err != nil {
@@ -97,15 +70,22 @@ func runWrapper() {
core.ShellPID = c.Process.Pid
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGWINCH)
// signal handling for resize and reload
sigCh := make(chan os.Signal, 2)
signal.Notify(sigCh, syscall.SIGWINCH, syscall.SIGUSR1)
go func() {
for range ch {
if err := pty.InheritSize(os.Stdin, ptmx); err != nil {
for s := range sigCh {
switch s {
case syscall.SIGWINCH:
_ = pty.InheritSize(os.Stdin, ptmx)
case syscall.SIGUSR1:
exe, _ := os.Executable()
os.Setenv("IRIS_RELOADED", "true")
_ = syscall.Exec(exe, os.Args, os.Environ())
}
}
}()
ch <- syscall.SIGWINCH
sigCh <- syscall.SIGWINCH
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
if err != nil {
@@ -234,12 +214,12 @@ func runWrapper() {
selected := overlay.Items[overlay.Cursor].Cmd
TermWrite([]byte(overlay.ClearAndDisable()))
// auto add space after tab for next suggestion in spec mode
if mode == "spec" || b == 0x09 {
selected += " "
}
// sync our naive buffer with the selected result
naiveBuffer = selected
mode = "spec" // reset to spec mode after selection
@@ -247,7 +227,7 @@ func runWrapper() {
// delete line (ctrl+u)
ptmx.Write([]byte{0x15})
ptmx.Write([]byte(selected))
if b == '\r' {
ptmx.Write([]byte{'\r'})
naiveBuffer = ""