Esempio n. 1
0
// termSignalListener returns a signal chan that closes when either (a) the process receives a termination
// signal: SIGTERM, SIGINT, or SIGHUP; or (b) the abort chan closes.
func termSignalListener(abort <-chan struct{}) <-chan struct{} {
	shouldQuit := make(chan struct{})
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh)

	go func() {
		defer close(shouldQuit)
		for {
			select {
			case <-abort:
				log.Infof("executor died, aborting")
				return
			case s, ok := <-sigCh:
				if !ok {
					return
				}
				switch s {
				case os.Interrupt, os.Signal(syscall.SIGTERM), os.Signal(syscall.SIGINT), os.Signal(syscall.SIGHUP):
					log.Infof("received signal %q, aborting", s)
					return
				case os.Signal(syscall.SIGCHLD): // who cares?
				default:
					log.Errorf("unexpected signal: %T %#v", s, s)
				}

			}
		}
	}()
	return shouldQuit
}
Esempio n. 2
0
File: proxy.go Progetto: 205c/git
func (p *Proxy) closeOnSignal() {
	ch := make(chan os.Signal, 10)
	signal.Notify(ch, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM), os.Signal(syscall.SIGHUP))
	sig := <-ch
	p.ul.Close()
	switch sig {
	case os.Signal(syscall.SIGHUP):
		log.Printf("graceful shutdown from signal: %v\n", sig)
	default:
		log.Fatalf("exiting from signal: %v\n", sig)
	}
}
Esempio n. 3
0
func (h *shutdownHandler) wait() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt, os.Signal(syscall.SIGTERM))
	sig := <-ch
	grohl.Log(grohl.Data{"fn": "shutdown", "at": "start", "signal": fmt.Sprint(sig)})
	h.shutdown(nil)
}
Esempio n. 4
0
func startServer(listenOn, dataDir string, pidFile string) {
	logger.Info("using version ", GITCOMMIT)
	logger.Info("starting server on ", listenOn)
	logger.Info("using dataDir ", dataDir)
	logger.Info("using pidFile", pidFile)

	if err := createPidFile(pidFile); err != nil {
		logger.Error(err)
		os.Exit(1)
	}
	defer removePidFile(pidFile)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
	go func() {
		sig := <-c
		logger.Debug("Received signal '%v', exiting\n", sig)
		removePidFile(pidFile)
		os.Exit(0)
	}()

	if err := http.ListenAndServe(listenOn, NewHandler(dataDir)); err != nil {
		logger.Error(err.Error())
	}
}
Esempio n. 5
0
// jobInitApi runs the remote api server `srv` as a daemon,
// Only one api server can run at the same time - this is enforced by a pidfile.
// The signals SIGINT, SIGKILL and SIGTERM are intercepted for cleanup.
func jobInitApi(job *engine.Job) string {
	job.Logf("Creating server")
	srv, err := NewServer(job.Eng, ConfigFromJob(job))
	if err != nil {
		return err.Error()
	}
	if srv.runtime.config.Pidfile != "" {
		job.Logf("Creating pidfile")
		if err := utils.CreatePidFile(srv.runtime.config.Pidfile); err != nil {
			log.Fatal(err)
		}
	}
	job.Logf("Setting up signal traps")
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
	go func() {
		sig := <-c
		log.Printf("Received signal '%v', exiting\n", sig)
		utils.RemovePidFile(srv.runtime.config.Pidfile)
		srv.Close()
		os.Exit(0)
	}()
	job.Eng.Hack_SetGlobalVar("httpapi.server", srv)
	if err := job.Eng.Register("create", srv.ContainerCreate); err != nil {
		return err.Error()
	}
	if err := job.Eng.Register("start", srv.ContainerStart); err != nil {
		return err.Error()
	}
	if err := job.Eng.Register("serveapi", srv.ListenAndServe); err != nil {
		return err.Error()
	}
	return "0"
}
Esempio n. 6
0
File: http.go Progetto: hSATAC/grace
// Used for checking if a process exists in pidfile
func processExistsAtPidString(pidStr string) bool {
	// Check if the process exists
	pid, err := strconv.Atoi(pidStr)
	if err != nil {
		return true // Convert error, can't determine.
	}

	process, err := os.FindProcess(pid)
	if err != nil {
		return true
	}

	err = process.Signal(os.Signal(syscall.Signal(0)))

	if err == nil {
		return true
	}

	errno, ok := err.(syscall.Errno)
	if !ok {
		return false
	}

	switch errno {
	case syscall.ESRCH:
		return false // Only here we could be sure the process does not exist.
	case syscall.EPERM:
		return true
	}

	return true
}
Esempio n. 7
0
func daemon(pidfile, addr string, port int, autoRestart bool) error {
	if addr != "127.0.0.1" {
		log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
	}
	if err := createPidFile(pidfile); err != nil {
		log.Fatal(err)
	}
	defer removePidFile(pidfile)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
	go func() {
		sig := <-c
		log.Printf("Received signal '%v', exiting\n", sig)
		removePidFile(pidfile)
		os.Exit(0)
	}()

	server, err := docker.NewServer(autoRestart)
	if err != nil {
		return err
	}

	return docker.ListenAndServe(fmt.Sprintf("%s:%d", addr, port), server, true)
}
Esempio n. 8
0
func (s *Service) stopService() error {
	s.stopTimer()
	s.mu.Lock()
	if !s.State.isRunState() {
		if s.State.canStop() {
			s.infof("stopped")
		}
		s.State = StateStopped
		s.mu.Unlock()
		return nil
	}
	prevState := s.State
	s.State = StateStopping
	s.infof("stopping")
	p := s.Cmd.Process
	s.mu.Unlock()
	if s != nil {
		stopped := isStoppedErr(p.Signal(os.Signal(syscall.SIGTERM)))
		if !stopped {
			select {
			case <-s.stopCh:
				stopped = true
			case <-time.After(10 * time.Second):
				stopped = isStoppedErr(p.Kill())
			}
			if !stopped {
				select {
				case <-s.stopCh:
				case <-time.After(2 * time.Second):
					// sending signal 0 checks that the process is
					// alive and we're allowed to send the signal
					// without actually sending anything
					if isStoppedErr(p.Signal(syscall.Signal(0))) {
						break
					}
					s.mu.Lock()
					s.State = prevState
					s.mu.Unlock()
					err := fmt.Errorf("could not stop, probably stuck")
					s.errorf("%v", err)
					return err
				}
			}
		}
	}
	s.mu.Lock()
	s.State = StateStopped
	s.Restarts = 0
	s.mu.Unlock()
	if s.Config.Log != nil {
		s.Config.Log.Close()
	}
	s.infof("stopped")
	return nil
}
Esempio n. 9
0
func (h *shutdownHandler) wait() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt, os.Signal(syscall.SIGTERM))
	sig := <-ch
	grohl.Log(grohl.Data{"fn": "shutdown", "at": "start", "signal": fmt.Sprint(sig)})
	// signal exit handlers
	close(h.done)
	// wait for exit handlers to finish
	h.mtx.Lock()
	os.Exit(0)
}
Esempio n. 10
0
func handleSignals() {
	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc)

	for s := range sigc {
		switch s {
		case os.Interrupt, os.Signal(syscall.SIGTERM):
			logger.Printf("Got signal %q; stopping all tasks.", s)
			for _, t := range GetTasks() {
				t.Stop()
			}
			logger.Printf("Tasks all stopped after %s; quitting.", s)
			os.Exit(0)
		case os.Signal(syscall.SIGCHLD):
			// Ignore.
		default:
			logger.Printf("unhandled signal: %T %#v", s, s)
		}
	}
}
func handleSignals() {
	signals := make(chan os.Signal, 1)
	signal.Notify(signals)

	for s := range signals {
		switch s {
		case os.Interrupt, os.Signal(syscall.SIGTERM):
			logger.Printf("%q: stop everything", s)
			haproxy.Kill()
			ctemplate.Kill()
			os.Exit(0)
		case os.Signal(syscall.SIGHUP):
			fmt.Println("SIGHUP!")
			haproxy.Restart()
		case os.Signal(syscall.SIGCHLD):
			// Ignore.
		default:
			logger.Printf("WTF %T %#v", s, s)
		}
	}
}
Esempio n. 12
0
func daemon(config *docker.DaemonConfig) error {
	if err := createPidFile(config.Pidfile); err != nil {
		log.Fatal(err)
	}
	defer removePidFile(config.Pidfile)

	server, err := docker.NewServer(config)
	if err != nil {
		return err
	}
	defer server.Close()

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
	go func() {
		sig := <-c
		log.Printf("Received signal '%v', exiting\n", sig)
		server.Close()
		removePidFile(config.Pidfile)
		os.Exit(0)
	}()

	chErrors := make(chan error, len(config.ProtoAddresses))
	for _, protoAddr := range config.ProtoAddresses {
		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
		if protoAddrParts[0] == "unix" {
			syscall.Unlink(protoAddrParts[1])
		} else if protoAddrParts[0] == "tcp" {
			if !strings.HasPrefix(protoAddrParts[1], "127.0.0.1") {
				log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
			}
		} else {
			server.Close()
			removePidFile(config.Pidfile)
			log.Fatal("Invalid protocol format.")
		}
		go func() {
			chErrors <- docker.ListenAndServe(protoAddrParts[0], protoAddrParts[1], server, true)
		}()
	}
	for i := 0; i < len(config.ProtoAddresses); i += 1 {
		err := <-chErrors
		if err != nil {
			return err
		}
	}
	return nil
}
Esempio n. 13
0
func daemon(pidfile string, protoAddrs []string, autoRestart, enableCors bool, flDns string) error {
	if err := createPidFile(pidfile); err != nil {
		log.Fatal(err)
	}
	defer removePidFile(pidfile)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
	go func() {
		sig := <-c
		log.Printf("Received signal '%v', exiting\n", sig)
		removePidFile(pidfile)
		os.Exit(0)
	}()
	var dns []string
	if flDns != "" {
		dns = []string{flDns}
	}
	server, err := docker.NewServer(autoRestart, enableCors, dns)
	if err != nil {
		return err
	}
	chErrors := make(chan error, len(protoAddrs))
	for _, protoAddr := range protoAddrs {
		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
		if protoAddrParts[0] == "unix" {
			syscall.Unlink(protoAddrParts[1])
		} else if protoAddrParts[0] == "tcp" {
			if !strings.HasPrefix(protoAddrParts[1], "127.0.0.1") {
				log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
			}
		} else {
			log.Fatal("Invalid protocol format.")
			os.Exit(-1)
		}
		go func() {
			chErrors <- docker.ListenAndServe(protoAddrParts[0], protoAddrParts[1], server, true)
		}()
	}
	for i := 0; i < len(protoAddrs); i += 1 {
		err := <-chErrors
		if err != nil {
			return err
		}
	}
	return nil
}
Esempio n. 14
0
// Daemon runs the remote api server `srv` as a daemon,
// Only one api server can run at the same time - this is enforced by a pidfile.
// The signals SIGINT, SIGKILL and SIGTERM are intercepted for cleanup.
func (srv *Server) Daemon() error {
	if err := utils.CreatePidFile(srv.runtime.config.Pidfile); err != nil {
		log.Fatal(err)
	}
	defer utils.RemovePidFile(srv.runtime.config.Pidfile)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
	go func() {
		sig := <-c
		log.Printf("Received signal '%v', exiting\n", sig)
		utils.RemovePidFile(srv.runtime.config.Pidfile)
		srv.Close()
		os.Exit(0)
	}()

	protoAddrs := srv.runtime.config.ProtoAddresses
	chErrors := make(chan error, len(protoAddrs))
	for _, protoAddr := range protoAddrs {
		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
		switch protoAddrParts[0] {
		case "unix":
			if err := syscall.Unlink(protoAddrParts[1]); err != nil && !os.IsNotExist(err) {
				log.Fatal(err)
			}
		case "tcp":
			if !strings.HasPrefix(protoAddrParts[1], "127.0.0.1") {
				log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
			}
		default:
			return fmt.Errorf("Invalid protocol format.")
		}
		go func() {
			chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], srv, true)
		}()
	}
	for i := 0; i < len(protoAddrs); i += 1 {
		err := <-chErrors
		if err != nil {
			return err
		}
	}
	return nil
}
Esempio n. 15
0
func isProcessAlive(p *os.Process) error {
	err := p.Signal(os.Signal(syscall.Signal(0)))
	if err == nil {
		return nil
	}
	errno, ok := err.(syscall.Errno)
	if !ok {
		return ErrDeadOwner
	}

	switch errno {
	case syscall.ESRCH:
		return ErrDeadOwner
	case syscall.EPERM:
		return nil
	default:
		return err
	}
}
Esempio n. 16
0
// Who owns the lockfile?
func (l Lockfile) GetOwner() (*os.Process, error) {
	name := string(l)

	// Ok, see, if we have a stale lockfile here
	content, err := ioutil.ReadFile(name)
	if err != nil {
		return nil, err
	}

	var pid int
	_, err = fmt.Sscanln(string(content), &pid)
	if err != nil {
		return nil, err
	}

	// try hard for pids. If no pid, the lockfile is junk anyway and we delete it.
	if pid > 0 {
		p, err := os.FindProcess(pid)
		if err != nil {
			return nil, err
		}
		err = p.Signal(os.Signal(syscall.Signal(0)))
		if err == nil {
			return p, nil
		}
		errno, ok := err.(syscall.Errno)
		if !ok {
			return nil, err
		}

		switch errno {
		case syscall.ESRCH:
			return nil, ErrDeadOwner
		case syscall.EPERM:
			return p, nil
		default:
			return nil, err
		}
	} else {
		return nil, ErrInvalidPid
	}
	panic("Not reached")
}
Esempio n. 17
0
func daemon(pidfile string) error {
	if err := createPidFile(pidfile); err != nil {
		log.Fatal(err)
	}
	defer removePidFile(pidfile)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
	go func() {
		sig := <-c
		log.Printf("Received signal '%v', exiting\n", sig)
		removePidFile(pidfile)
		os.Exit(0)
	}()

	service, err := docker.NewServer()
	if err != nil {
		return err
	}
	return rcli.ListenAndServe("tcp", "127.0.0.1:4242", service)
}
Esempio n. 18
0
File: pid.go Progetto: Wang/pid
func IsActive(pid int) (bool, error) {
	if pid <= 0 {
		return false, errors.New("process id error.")
	}
	p, err := os.FindProcess(pid)
	if err != nil {
		if Debug {
			fmt.Printf("find process: %s\n", err.Error())
		}
		return false, err
	}

	if err := p.Signal(os.Signal(syscall.Signal(0))); err != nil {
		if Debug {
			fmt.Printf("send signal [0]: %s\n", err.Error())
		}
		return false, err
	}

	return true, nil
}
Esempio n. 19
0
func daemon(pidfile string, autoRestart bool) error {
	if err := createPidFile(pidfile); err != nil {
		log.Fatal(err)
	}
	defer removePidFile(pidfile)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
	go func() {
		sig := <-c
		log.Printf("Received signal '%v', exiting\n", sig)
		removePidFile(pidfile)
		os.Exit(0)
	}()

	server, err := docker.NewServer(autoRestart)
	if err != nil {
		return err
	}

	return docker.ListenAndServe("0.0.0.0:4243", server, true)
}
Esempio n. 20
0
func isPidActive(pid int) (bool, error) {
	p, err := os.FindProcess(pid)
	if err != nil {
		return false, nil
	}
	err = p.Signal(os.Signal(syscall.Signal(0)))
	if err == nil {
		return true, nil
	}
	errno, ok := err.(syscall.Errno)
	if !ok {
		return false, nil // dead owner
	}
	switch errno {
	case syscall.ESRCH:
		return false, nil // dead owner
	case syscall.EPERM:
		return true, nil
	default:
		return false, err
	}
}
Esempio n. 21
0
func (m *Monitor) Run() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Signal(syscall.SIGCHLD))
	if m.set != nil {
		go m.set.Run()
	}
loop:
	for {
		select {
		case <-ch:
			m.waitForExited()
		case <-m.quit.stop:
			m.quit.sendStopped()
			break loop
		}
	}
	signal.Stop(ch)
	close(ch)
	if m.set != nil {
		m.set.Stop()
	}
}
Esempio n. 22
0
func (h *signalsHandler) forward(p *process) int {

	pid1 := p.pid()

	for s := range h.signals {
		log.Debugf("signal: %q", s)

		switch s {
		case syscall.SIGWINCH:
			p.resizePty()

		case syscall.SIGCHLD:
			//child process died, dock will exit
			//sending sigterm to every remaining processes before calling wait4
			if err := signalAllDescendants(syscall.SIGTERM); err != nil {
				log.Debugf("failed to send sigterm signal: %v", err)
			}

			go func() {
				<-time.After(killTimeout * time.Second)
				log.Debugf("kill timed out")
				if err := signalAllDescendants(syscall.SIGKILL); err != nil {
					log.Debugf("failed to send sigkill signal: %v", err)
				}
			}()

			//waiting for all processes to die
			log.Debug("reaping all children")
			exits, err := reap()
			log.Debug("children reaped")
			if err != nil {
				log.Error(err)
			}

			for _, e := range exits {
				if e.pid == pid1 {
					p.wait()
					return e.status
				}
			}

		case syscall.SIGINT:
			fallthrough
		case syscall.SIGTERM:
			fallthrough
		case syscall.SIGQUIT:
			//stopping signals
			sigToForward := s

			if h.authority {
				blocked, err := isSignalBlocked(pid1, s)
				if err != nil {
					log.Error(err)
					goto forward
				}
				ignored, err := isSignalIgnored(pid1, s)
				if err != nil {
					log.Error(err)
					goto forward
				}
				if blocked || ignored {
					sigToForward = os.Signal(syscall.SIGKILL)
				}
			}

		forward:
			if err := p.signal(sigToForward); err != nil {
				log.Error(err)
			}

		default:

			//simply forward the signal to the process
			if err := p.signal(s); err != nil {
				log.Error(err)
			}
		}
	}

	panic("-- this line should never been executed --")
}
Esempio n. 23
0
func main() {
	if err := globalFlags.Parse(os.Args[1:]); err != nil {
		Fatalln(err)
	}
	globalConfig.command = globalFlags.Args()
	globalConfig.source = "[commandline]"
	if verbose {
		printGlobals()
	}
	switch strings.ToLower(flagDecoration) {
	case "none":
		decoration = DecorationNone
	case "plain":
		decoration = DecorationPlain
	case "fancy":
		decoration = DecorationFancy
	default:
		Fatalln(fmt.Sprintf("Invalid decoration %s. Choices: none, plain, fancy.", flagDecoration))
	}

	var configs []*Config
	if flagConf == "" {
		if flagSequential {
			Fatalln("Cannot set --sequential without --config (because you cannot specify multiple commands).")
		}
		configs = []*Config{globalConfig}
	} else {
		if anyNonGlobalsRegistered() {
			Fatalln("Cannot set other flags along with --config other than --sequential, --verbose, and --decoration.")
		}
		var err error
		configs, err = ReadConfigs(flagConf)
		if err != nil {
			Fatalln("Could not parse configs: ", err)
		}
		if len(configs) == 0 {
			Fatalln("No configurations found")
		}
	}

	for _, config := range configs {
		reflex, err := NewReflex(config)
		if err != nil {
			Fatalln("Could not make reflex for config:", err)
		}
		if verbose {
			fmt.Println(reflex)
		}
		reflexes = append(reflexes, reflex)
	}

	// Catch ctrl-c and make sure to kill off children.
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt)
	signal.Notify(signals, os.Signal(syscall.SIGTERM))
	go func() {
		s := <-signals
		reason := fmt.Sprintf("Interrupted (%s). Cleaning up children...", s)
		cleanup(reason)
	}()
	defer cleanup("Cleaning up.")

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		Fatalln(err)
	}
	defer watcher.Close()

	changes := make(chan string)
	broadcastChanges := make([]chan string, len(reflexes))
	done := make(chan error)
	for i := range reflexes {
		broadcastChanges[i] = make(chan string)
	}
	go watch(".", watcher, changes, done, reflexes)
	go broadcast(broadcastChanges, changes)
	go printOutput(stdout, os.Stdout)

	for i, reflex := range reflexes {
		reflex.Start(broadcastChanges[i])
	}

	Fatalln(<-done)
}
Esempio n. 24
0
	sync.Mutex
	server *graceful.Server

	// Interrupted is true if the application is in the process of shutting down.
	Interrupted bool

	// CancelOnShutdown tells whether existing requests should be canceled when shutdown is
	// triggered (true) or whether to wait until the requests complete (false).
	CancelOnShutdown bool
}

// InterruptSignals is the list of signals that initiate graceful shutdown.
// Note that only SIGINT is supported on Windows so this list should be
// overridden by the caller when running on that platform.
var InterruptSignals = []os.Signal{
	os.Signal(syscall.SIGINT),
	os.Signal(syscall.SIGTERM),
	os.Signal(syscall.SIGQUIT),
}

// NewGraceful returns a goa application that uses a graceful shutdown server.
func NewGraceful(name string, cancelOnShutdown bool) Service {
	app, _ := New(name).(*Application)
	return &GracefulApplication{Application: app, CancelOnShutdown: cancelOnShutdown}
}

// ListenAndServe starts the HTTP server and sets up a listener on the given host/port.
func (gapp *GracefulApplication) ListenAndServe(addr string) error {
	gapp.setup(addr)
	gapp.Info("listen", "addr", addr)
	if err := gapp.server.ListenAndServe(); err != nil {
Esempio n. 25
0
// WaitSIGHUP blocks until a SIGHUP signal is received.
func WaitSIGHUP() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Signal(syscall.SIGHUP))
	<-ch
}
Esempio n. 26
0
File: run.go Progetto: Cardinala/hk
func runRun(cmd *Command, args []string) {
	cols, err := term.Cols()
	if err != nil {
		log.Fatal(err)
	}
	lines, err := term.Lines()
	if err != nil {
		log.Fatal(err)
	}
	data := make(url.Values)
	if !detachedRun {
		data.Add("attach", "true")
		data.Add("ps_env[TERM]", os.Getenv("TERM"))
		data.Add("ps_env[COLUMNS]", strconv.Itoa(cols))
		data.Add("ps_env[LINES]", strconv.Itoa(lines))
	}
	data.Add("command", strings.Join(args, " "))

	resp := struct {
		Url *string `json:"rendezvous_url,omitempty"`
	}{}

	must(Post(&v2{&resp}, "/apps/"+mustApp()+"/ps", data))

	if detachedRun {
		return
	}

	u, err := url.Parse(*resp.Url)
	if err != nil {
		log.Fatal(err)
	}

	cn, err := tls.Dial("tcp", u.Host, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer cn.Close()

	br := bufio.NewReader(cn)

	_, err = io.WriteString(cn, u.Path[1:]+"\r\n")
	if err != nil {
		log.Fatal(err)
	}

	for {
		_, pre, err := br.ReadLine()
		if err != nil {
			log.Fatal(err)
		}
		if !pre {
			break
		}
	}

	if term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) {
		err = term.MakeRaw(os.Stdin)
		if err != nil {
			log.Fatal(err)
		}
		defer term.Restore(os.Stdin)

		sig := make(chan os.Signal)
		signal.Notify(sig, os.Signal(syscall.SIGQUIT), os.Interrupt)
		go func() {
			defer term.Restore(os.Stdin)
			for sg := range sig {
				switch sg {
				case os.Interrupt:
					cn.Write([]byte{3})
				case os.Signal(syscall.SIGQUIT):
					cn.Write([]byte{28})
				default:
					panic("not reached")
				}
			}
		}()
	}

	errc := make(chan error)
	cp := func(a io.Writer, b io.Reader) {
		_, err := io.Copy(a, b)
		errc <- err
	}

	go cp(os.Stdout, br)
	go cp(cn, os.Stdin)
	if err = <-errc; err != nil {
		log.Fatal(err)
	}
}
Esempio n. 27
0
package main

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

// DeadlySignals lists signals, which lead to process termination by default
// and can be caught by the process receiving them.
var DeadlySignals = []os.Signal{
	os.Signal(syscall.SIGTERM),
	os.Signal(syscall.SIGHUP),
	os.Signal(syscall.SIGINT),
}

// ReceiveDeadlySignals requests delivery of DeadlySignals on channel "on"
func ReceiveDeadlySignals() (on chan os.Signal) {
	on = make(chan os.Signal, 1)
	signal.Notify(on, DeadlySignals...)
	return on
}

// IgnoreDeadlySignals stops delivery of DeadlySignals on channel "on"
func IgnoreDeadlySignals(on chan os.Signal) {
	if on != nil {
		signal.Stop(on)
	}
}
Esempio n. 28
0
func main() {
	if err := globalFlags.Parse(os.Args[1:]); err != nil {
		Fatalln(err)
	}
	if verbose {
		printGlobals()
	}
	switch strings.ToLower(flagDecoration) {
	case "none":
		decoration = DecorationNone
	case "plain":
		decoration = DecorationPlain
	case "fancy":
		decoration = DecorationFancy
	default:
		Fatalln(fmt.Sprintf("Invalid decoration %s. Choices: none, plain, fancy.", flagDecoration))
	}

	if flagConf == "" {
		reflex, err := NewReflex(globalConfig, globalFlags.Args())
		if err != nil {
			Fatalln(err)
		}
		if verbose {
			reflex.PrintInfo("commandline")
		}
		reflexes = append(reflexes, reflex)
		if flagSequential {
			Fatalln("Cannot set --sequential without --config (because you cannot specify multiple commands).")
		}
	} else {
		if anyNonGlobalsRegistered() {
			Fatalln("Cannot set other flags along with --config other than --sequential, --verbose, and --decoration.")
		}

		// Now open the configuration file.
		// As a special case we read the config from stdin if --config is set to "-"
		var config io.ReadCloser
		if flagConf == "-" {
			config = os.Stdin
		} else {
			configFile, err := os.Open(flagConf)
			if err != nil {
				Fatalln(err)
			}
			config = configFile
		}

		scanner := bufio.NewScanner(config)
		lineNo := 0
		for scanner.Scan() {
			lineNo++
			errorMsg := fmt.Sprintf("Error on line %d of %s:", lineNo, flagConf)
			config := &Config{}
			flags := flag.NewFlagSet("", flag.ContinueOnError)
			registerFlags(flags, config)
			parts, err := shellquote.Split(scanner.Text())
			if err != nil {
				Fatalln(errorMsg, err)
			}
			// Skip empty lines and comments (lines starting with #).
			if len(parts) == 0 || strings.HasPrefix(parts[0], "#") {
				continue
			}
			if err := flags.Parse(parts); err != nil {
				Fatalln(errorMsg, err)
			}
			reflex, err := NewReflex(config, flags.Args())
			if err != nil {
				Fatalln(errorMsg, err)
			}
			if verbose {
				reflex.PrintInfo(fmt.Sprintf("%s, line %d", flagConf, lineNo))
			}
			reflexes = append(reflexes, reflex)
		}
		if err := scanner.Err(); err != nil {
			Fatalln(err)
		}
		config.Close()
	}

	// Catch ctrl-c and make sure to kill off children.
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt)
	signal.Notify(signals, os.Signal(syscall.SIGTERM))
	go func() {
		s := <-signals
		reason := fmt.Sprintf("Interrupted (%s). Cleaning up children...", s)
		cleanup(reason)
	}()
	defer cleanup("Cleaning up.")

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		Fatalln(err)
	}
	defer watcher.Close()

	rawChanges := make(chan string)
	allRawChanges := make([]chan<- string, len(reflexes))
	done := make(chan error)
	for i, reflex := range reflexes {
		allRawChanges[i] = reflex.rawChanges
	}
	go watch(".", watcher, rawChanges, done)
	go broadcast(rawChanges, allRawChanges)

	go printOutput(stdout, os.Stdout)

	for _, reflex := range reflexes {
		go filterMatching(reflex.rawChanges, reflex.filtered, reflex)
		go batch(reflex.filtered, reflex.batched, reflex)
		go runEach(reflex.batched, reflex)
		if reflex.startService {
			// Easy hack to kick off the initial start.
			infoPrintln(reflex.id, "Starting service")
			runCommand(reflex, "", stdout)
		}
	}

	Fatalln(<-done)
}
Esempio n. 29
0
File: run.go Progetto: herokai/hk
func runRun(cmd *Command, args []string) {
	if len(args) == 0 {
		cmd.PrintUsage()
		os.Exit(2)
	}
	appname := mustApp()

	cols, err := term.Cols()
	if err != nil {
		printFatal(err.Error())
	}
	lines, err := term.Lines()
	if err != nil {
		printFatal(err.Error())
	}

	attached := !detachedRun
	opts := heroku.DynoCreateOpts{Attach: &attached}
	if attached {
		env := map[string]string{
			"COLUMNS": strconv.Itoa(cols),
			"LINES":   strconv.Itoa(lines),
			"TERM":    os.Getenv("TERM"),
		}
		opts.Env = &env
	}
	if dynoSize != "" {
		if !strings.HasSuffix(dynoSize, "X") {
			cmd.PrintUsage()
			os.Exit(2)
		}
		opts.Size = &dynoSize
	}

	command := strings.Join(args, " ")
	dyno, err := client.DynoCreate(appname, command, &opts)
	must(err)

	if detachedRun {
		log.Printf("Ran `%s` on %s as %s, detached.", dyno.Command, appname, dyno.Name)
		return
	}
	log.Printf("Running `%s` on %s as %s:", dyno.Command, appname, dyno.Name)

	u, err := url.Parse(*dyno.AttachURL)
	if err != nil {
		printFatal(err.Error())
	}

	cn, err := tls.Dial("tcp", u.Host, nil)
	if err != nil {
		printFatal(err.Error())
	}
	defer cn.Close()

	br := bufio.NewReader(cn)

	_, err = io.WriteString(cn, u.Path[1:]+"\r\n")
	if err != nil {
		printFatal(err.Error())
	}

	for {
		_, pre, err := br.ReadLine()
		if err != nil {
			printFatal(err.Error())
		}
		if !pre {
			break
		}
	}

	if term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) {
		err = term.MakeRaw(os.Stdin)
		if err != nil {
			printFatal(err.Error())
		}
		defer term.Restore(os.Stdin)

		sig := make(chan os.Signal)
		signal.Notify(sig, os.Signal(syscall.SIGQUIT), os.Interrupt)
		go func() {
			defer term.Restore(os.Stdin)
			for sg := range sig {
				switch sg {
				case os.Interrupt:
					cn.Write([]byte{3})
				case os.Signal(syscall.SIGQUIT):
					cn.Write([]byte{28})
				default:
					panic("not reached")
				}
			}
		}()
	}

	errc := make(chan error)
	cp := func(a io.Writer, b io.Reader) {
		_, err := io.Copy(a, b)
		errc <- err
	}

	go cp(os.Stdout, br)
	go cp(cn, os.Stdin)
	if err = <-errc; err != nil {
		printFatal(err.Error())
	}
}
Esempio n. 30
0
func (h *handler) wait() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt, os.Signal(syscall.SIGTERM))
	<-ch
	h.exit(nil, 0, nil)
}