Sfoglia il codice sorgente

rewrite main logic to properly stop the process.

e.g. ensure that it's children are also stopped. the code might be
linux-specific at the moment, but i don't quite know how to fix that.
Lucas Stadler 11 anni fa
parent
commit
4c748b257a
1 ha cambiato i file con 38 aggiunte e 39 eliminazioni
  1. 38 39
      go/qst.go

+ 38 - 39
go/qst.go

1
package main
1
package main
2
2
3
import "errors"
3
import "flag"
4
import "flag"
4
import "fmt"
5
import "fmt"
5
import "log"
6
import "log"
7
import "os/exec"
8
import "os/exec"
8
import "path"
9
import "path"
9
import "strings"
10
import "strings"
10
import "sync"
11
import "syscall"
11
import "time"
12
import "time"
12
13
13
/*
14
/*
60
61
61
	ext := path.Ext(file)
62
	ext := path.Ext(file)
62
	fn, found := mappings[ext]
63
	fn, found := mappings[ext]
63
	if found {
64
		runAndWatch(file, fn(file))
65
	} else {
66
		fmt.Fprintf(os.Stderr, "Error: No command defined for %s files", ext)
67
		os.Exit(1)
64
	if !found {
65
		log.Fatalf("error: no mapping found for `%s'", file)
68
	}
66
	}
69
}
70
67
71
func runAndWatch(file string, cmdLine string) {
72
	// run command, if file changes (mtime) restart command
68
	runner := MakeRunner(fn(file))
69
	runner.Start()
73
	lastMtime := time.Now()
70
	lastMtime := time.Now()
74
	cmd := ShellCmd(cmdLine)
75
	cmd.Start()
76
77
	for {
71
	for {
78
		info, err := os.Stat(file)
72
		info, err := os.Stat(file)
79
		if err != nil {
80
			log.Fatalf("Error: %s disappeared, exiting.", file)
73
		if os.IsNotExist(err) {
74
			log.Fatalf("`%s' disappeared, exiting")
81
		}
75
		}
82
76
83
		mtime := info.ModTime()
77
		mtime := info.ModTime()
84
		if mtime.After(lastMtime) {
78
		if mtime.After(lastMtime) {
85
			log.Printf("%s changed, rerunning", file)
86
			cmd.Restart()
79
			log.Printf("`%s' changed, trying to restart", file)
80
			runner.Restart()
87
		}
81
		}
88
82
89
		lastMtime = mtime
83
		lastMtime = mtime
91
	}
85
	}
92
}
86
}
93
87
94
type RestartableCommand struct {
95
	Cmd  *exec.Cmd
96
	Lock sync.Mutex
97
	Name string
98
	Args []string
88
type Runner struct {
89
	cmd      *exec.Cmd
90
	shellCmd string
91
	started  bool
99
}
92
}
100
93
101
func ShellCmd(cmd string) RestartableCommand {
102
	return RestartableCommand{nil, sync.Mutex{}, "sh", []string{"-c", cmd}}
94
func MakeRunner(shellCmd string) *Runner {
95
	return &Runner{nil, shellCmd, false}
103
}
96
}
104
97
105
func (c *RestartableCommand) Start() {
106
	c.Cmd = exec.Command(c.Name, c.Args...)
107
	c.Cmd.Stderr = os.Stderr
108
	c.Cmd.Stdout = os.Stdout
109
	c.Lock.Lock()
98
func (r *Runner) Start() error {
99
	if r.started {
100
		return errors.New("already started, use Restart()")
101
	}
102
103
	r.started = true
110
	go func() {
104
	go func() {
111
		c.Cmd.Run()
112
		c.Lock.Unlock()
105
		for {
106
			log.Printf("running %s", r.shellCmd)
107
			r.cmd = exec.Command("sh", "-c", r.shellCmd)
108
			r.cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
109
			err := r.cmd.Run()
110
			log.Printf("%s finished: %s", r.shellCmd, err)
111
112
			time.Sleep(1 * time.Second)
113
		}
113
	}()
114
	}()
114
}
115
115
116
func (c *RestartableCommand) Restart() {
117
	c.Cmd.Process.Kill()
118
	c.Start()
116
	return nil
119
}
117
}
120
118
121
func runShellCmd(cmd string) {
122
	log.Printf("Running: `%s'", cmd)
123
	output, err := exec.Command("sh", "-c", cmd).CombinedOutput()
124
	os.Stderr.Write(output)
125
	log.Printf("Error running command: %s\n", err.Error())
119
func (r *Runner) Restart() error {
120
	pgid, err := syscall.Getpgid(r.cmd.Process.Pid)
121
	if err == nil {
122
		syscall.Kill(-pgid, syscall.SIGTERM)
123
	}
124
	return err
126
}
125
}
127
126
128
func isFile(file string) bool {
127
func isFile(file string) bool {