cespare / reflex

Run a command when files change
MIT License
3.35k stars 135 forks source link

Why the negative 1? #57

Closed zwhitchcox closed 5 years ago

zwhitchcox commented 5 years ago

For gosh sake's I've been trying to debug my own code for a while now, and I look to your code for inspiration, and the thing that fixed it was changing

syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
syscall.Kill(-1*cmd.Process.Pid, syscall.SIGKILL)

as you did in your code. I just thought it looked odd and there must be a reason for it, so I tried it and it fixed my code!!!

So, I just have to ask why on earth. I guess it's casting it to an int? But why does that matter?

cespare commented 5 years ago

Those are equivalent. I like your way better. I think that maybe changing that wasn't having the effect you thought it was?

zwhitchcox commented 5 years ago

Haha, yes, I found out the actual reason was I was intercepting the signal to kill, but that was just on my test script, not the actual script... have to figure out if it was the same problem in my actual code tomorrow

zwhitchcox commented 5 years ago

Yeah, it turns out I had this code

    c := make(chan os.Signal, 2)
    signal.Notify(c, os.Interrupt, os.Kill)
    go func() {
        <-c
        syscall.Kill(-serverCmd.Process.Pid, syscall.SIGKILL)
        os.Exit(1)
    }()

that was keeping the process alive.

goroutines are hard :(

Thanks for your help though!

zwhitchcox commented 5 years ago

Basically, the problem is I'm running this code

    c := make(chan os.Signal, 2)
    signal.Notify(c, os.Interrupt, os.Kill)
    go func() {
        defer close(c)
        <-c
        syscall.Kill(-apiCmd.Process.Pid, syscall.SIGKILL)
        syscall.Kill(-uiCmd.Process.Pid, syscall.SIGKILL)
        os.Exit(1)
    }()

    go func() {
        apiCmd = exec.Command("go", "run", "./scripts/watch-server.go")
        apiCmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
        apiCmd.Stdout = os.Stdout
        apiCmd.Stderr = os.Stderr
        apiCmd.Run()
    }()

    uiCmd = exec.Command("yarn", "dev:ui")
    uiCmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
    uiCmd.Stdout = os.Stdout
    uiCmd.Stderr = os.Stderr
    uiCmd.Run()

And if I don't run the apiCmd in a goroutine, it never runs the uiCmd, but if I take it out, when I end the process, the apiCmd keeps running even after I end the process.

zwhitchcox commented 5 years ago

Ok, finally fixed it...this is my code if you're interested

package main

import (
    "log"
    "os"
    "os/exec"
    "os/signal"
    "syscall"
)

var apiCmd, uiCmd *exec.Cmd

func main() {
    c := make(chan os.Signal, 2)
    signal.Notify(c, os.Interrupt, os.Kill)
    go func() {
    }()

    go func() {
        apiCmd = exec.Command("go", "run", "./scripts/watch-server.go")
        apiCmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
        apiCmd.Stdout = os.Stdout
        apiCmd.Stderr = os.Stderr
        apiCmd.Run()
    }()

    go func() {
        uiCmd = exec.Command("yarn", "dev:ui")
        uiCmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
        uiCmd.Stdout = os.Stdout
        uiCmd.Stderr = os.Stderr
        uiCmd.Run()
    }()
    defer close(c)
    <-c
    log.Println("closing")
    syscall.Kill(-apiCmd.Process.Pid, syscall.SIGKILL)
    syscall.Kill(-uiCmd.Process.Pid, syscall.SIGKILL)
    os.Exit(1)
}