func startWrapper(filesChanged chan string) *exec.Cmd { cmd := exec.Command(executablePath()) var err error if watcherIn, err = cmd.StdinPipe(); err != nil { terminate(err.Error()) } if watcherOut, err = cmd.StdoutPipe(); err != nil { terminate(err.Error()) } if watcherErr, err = cmd.StderrPipe(); err != nil { terminate(err.Error()) } cmd.Start() go func() { buf := make([]byte, 2048) for { n, err := watcherOut.Read(buf) if err != nil { time.Sleep(500 * time.Millisecond) slog.Red("Failed to read from FileSystem watcher process: " + err.Error()) } message := strings.TrimSpace(string(buf[:n])) files := strings.Split(message, "\n") for _, file := range files { filesChanged <- file } } }() go func() { err := cmd.Wait() // gross, but this is an easy way to work around the case where // signal propagation hits the wrapper before the master disables logging time.Sleep(100 * time.Millisecond) terminate("The FS watcher process crashed: " + err.Error()) }() return cmd }
func ErrorUnableToAcceptSocketConnection() { slog.Red("Unable to accept socket connection.") }
func ErrorCantCreateListener() { ExitNow(1, func() { slog.Red("It looks like Zooms is already running. If not, remove {yellow}.zooms.sock{red} and try again.") }) }
func ErrorConfigFileInvalidFormat() { if slog.Red("The config file {yellow}zooms.json{red} is not in the correct format.") { os.Exit(1) } }
// The config file is loaded before any goroutines are launched that require cleanup, // and our exitNow goroutine has not been spawned yet, so we will just explicitly exit // in the json-related errors.. func ErrorConfigFileInvalidJson() { if slog.Red("The config file {yellow}zooms.json{red} contains invalid JSON and could not be parsed.") { os.Exit(1) } }
func ErrorConfigCommandCrashed(output string) { ExitNow(1, func() { slog.Red("Couldn't boot application. {yellow}command{red} terminated with this output:") fmt.Println(output) }) }
func ErrorConfigCommandCouldntStart(msg, output string) { ExitNow(1, func() { slog.Red("Failed to initialize application from {yellow}zooms.json{red}.") slog.Red("The json file is valid, but the {yellow}command{red} could not be started:\n\x1b[0m" + output) }) }
func ErrorCantConnectToMaster() { slog.Red("Can't connect to master. Run {yellow}zooms start{red} first.\r") }
func Error(msg string) { ExitNow(1, func() { slog.Red(msg) }) }
func terminate(message string) { slog.Red(message) println(message) proc, _ := os.FindProcess(os.Getpid()) proc.Signal(syscall.SIGTERM) }