Example #1
0
// Start runs the coprocess
func (coprocess *Coprocess) Start() {
	log.Debugf("coprocess[%s].Start", coprocess.Name)
	fields := log.Fields{"process": "coprocess", "coprocess": coprocess.Name}
	stdout := utils.NewLogWriter(fields, log.InfoLevel)
	stderr := utils.NewLogWriter(fields, log.DebugLevel)
	coprocess.logWriters = []io.WriteCloser{stdout, stderr}
	defer coprocess.closeLogs()

	// always reset restartsRemain when we load the config
	coprocess.restartsRemain = coprocess.restartLimit
	for {
		if coprocess.restartLimit != unlimitedRestarts &&
			coprocess.restartsRemain <= haltRestarts {
			break
		}
		cmd := utils.ArgsToCmd(coprocess.Args)
		coprocess.cmd = cmd
		cmd.Stdout = stdout
		cmd.Stderr = stderr
		if _, err := utils.ExecuteAndWait(cmd); err != nil {
			log.Errorf("coprocess[%s] exited: %s", coprocess.Name, err)
		}
		log.Debugf("coprocess[%s] exited", coprocess.Name)
		if !coprocess.restart {
			break
		}
		coprocess.restartsRemain--
	}
}
// Test handler for SIGTERM. Note that the SIGCHLD handler is fired
// by this same test, but that we don't have a separate unit test
// because they'll interfere with each other's state.
func TestTerminateSignal(t *testing.T) {

	app := getSignalTestConfig()
	startTime := time.Now()
	go func() {
		if exitCode, _ := utils.ExecuteAndWait(app.Command); exitCode != 2 {
			t.Fatalf("Expected exit code 2 but got %d", exitCode)
		}
	}()
	// we need time for the forked process to start up and this is async
	runtime.Gosched()
	time.Sleep(10 * time.Millisecond)

	app.Terminate()
	elapsed := time.Since(startTime)
	if elapsed.Seconds() > float64(app.StopTimeout) {
		t.Fatalf("Expected elapsed time <= %d seconds, but was %.2f",
			app.StopTimeout, elapsed.Seconds())
	}
}
Example #3
0
// Run starts the application and blocks until finished
func (a *App) Run() {
	// Set up handlers for polling and to accept signal interrupts
	if 1 == os.Getpid() {
		reapChildren()
	}
	args := getArgs(flag.Args())
	command, err := utils.ParseCommandArgs(args)
	if err != nil {
		log.Errorf("Unable to parse command arguments: %v", err)
	}
	a.handleSignals()
	// Run the preStart handler, if any, and exit if it returns an error
	if preStartCode, err := utils.RunWithFields(a.PreStartCmd, log.Fields{"process": "PreStart"}); err != nil {
		os.Exit(preStartCode)
	}
	a.handleCoprocesses()
	a.handlePolling()

	if len(args) != 0 {
		// Run our main application and capture its stdout/stderr.
		// This will block until the main application exits and then os.Exit
		// with the exit code of that application.
		a.Command = command
		command.Stderr = os.Stderr
		command.Stdout = os.Stdout
		code, err := utils.ExecuteAndWait(command)
		if err != nil {
			log.Println(err)
		}
		// Run the PostStop handler, if any, and exit if it returns an error
		if postStopCode, err := utils.RunWithFields(a.PostStopCmd, log.Fields{"process": "PostStop"}); err != nil {
			os.Exit(postStopCode)
		}
		os.Exit(code)
	}

	// block forever, as we're polling in the two polling functions and
	// did not os.Exit by waiting on an external application.
	select {}
}