Ejemplo n.º 1
0
/*
	Write exit information to 'exitFile'
*/
func (be *BdsExec) updateExitFile(exitStr string) {
	if (be.exitFile != "") && (be.exitFile != "-") {
		if DEBUG {
			log.Printf("Debug: Writing exit status '%s' to exit file '%s'\n", exitStr, be.exitFile)
		}
		fileutil.WriteFile(be.exitFile, exitStr)
	}
}
Ejemplo n.º 2
0
/*
	Execute a command enforcing a timeout and writing exit status to 'exitFile'
*/
func (be *BdsExec) executeCommandTimeout(osSignal chan os.Signal) int {
	if DEBUG {
		log.Printf("Debug, executeCommandTimeout\n")
	}

	// Wait for execution to finish or timeout
	exitStr := ""
	if be.timeSecs <= 0 {
		be.timeSecs = 31536000 // Default: One year
	}

	// Create a timeout process
	// References: http://blog.golang.org/2010/09/go-concurrency-patterns-timing-out-and.html
	exitCode := make(chan string, 1)
	go execute(be.cmd, exitCode)

	// Wait until executions ends, timeout or OS signal
	kill := false
	run := true
	for run {
		select {
		case exitStr = <-exitCode:
			kill = false
			run = false
			if DEBUG {
				log.Printf("Debug, executeCommandTimeout: Execution finished (%s)\n", exitStr)
			}

		case <-time.After(time.Duration(be.timeSecs) * time.Second):
			run = false
			kill = true
			exitStr = "Time out"
			if DEBUG {
				log.Printf("Debug, executeCommandTimeout: Timeout!\n")
			}

		case sig := <-osSignal:
			// Ignore some signals (e.g. "window changed")
			sigStr := sig.String()
			if sigStr != "window changed" && sigStr != "child exited" && sigStr != "window size changes" {
				if VERBOSE || DEBUG {
					log.Printf("bds: Received OS signal '%s'\n", sigStr)
				}

				kill = true
				exitStr = "Signal received"
				run = false
			}
		}
	}

	// Write exitCode to file
	if (be.exitFile != "") && (be.exitFile != "-") {
		if DEBUG {
			log.Printf("Info: Writing exit status '%s' to exit file '%s'\n", exitStr, be.exitFile)
		}
		fileutil.WriteFile(be.exitFile, exitStr)
	}

	// Should we kill child process?
	if kill {
		if DEBUG {
			log.Printf("Info: Killing process\n")
		}
		be.cmd.Process.Kill()
		be.cmd.Process.Wait() // Reap their souls
	}

	if kill {
		// Should we kill all process groups from taskLoggerFile?
		if be.taskLoggerFile != "" {
			be.taskLoggerCleanUpAll()
		}

		// Send a SIGKILL to the process group (just in case any child process is still executing)
		if DEBUG {
			log.Printf("Info: Killing process group: kill(0, SIGHUP)\n")
		}
		syscall.Kill(0, syscall.SIGHUP)
	}

	// OK? exit value should be zero
	if exitStr == "0" {
		return EXITCODE_OK
	}

	// Timeout?
	if exitStr == "Time out" {
		return EXITCODE_TIMEOUT
	}

	return EXITCODE_ERROR
}