Merge "Relaunch execserver on after a link error."
diff --git a/cherry/adb.go b/cherry/adb.go
index 2a1e6c5..2f1bb75 100644
--- a/cherry/adb.go
+++ b/cherry/adb.go
@@ -346,6 +346,12 @@
)
}
+func RelaunchAndroidExecServer (adbSerialNumber string) error {
+ return runCommands(
+ exec.Command("adb", "-s", adbSerialNumber, "shell", "am", "start", "-n", "com.drawelements.deqp/.execserver.ServiceStarter"),
+ )
+}
+
func RemoveADBPortForward (adbSerialNumber string, localPort int) error {
forwardInfos, err := getADBPortForwardInfos()
if err != nil { return err }
diff --git a/cherry/tcplink.go b/cherry/tcplink.go
index 717520d..c7c1f39 100644
--- a/cherry/tcplink.go
+++ b/cherry/tcplink.go
@@ -66,6 +66,16 @@
STOP_REQUEST_TIMEOUT_SECONDS = 10
)
+// Enums
+
+type ExecStatusCode int
+
+const (
+ EXEC_STATUS_DONE ExecStatusCode = iota
+ EXEC_STATUS_LINK_ERROR
+ EXEC_STATUS_TIMEOUT
+)
+
// TestExecutorEvent
type TestExecutorEvent interface {
@@ -97,6 +107,7 @@
}
type EventExecutionFinished struct {
+ status ExecStatusCode
}
// LineSplitter
@@ -119,7 +130,6 @@
func (link *CommLinkTcpIp) handleConnection (conn net.Conn, eventChannel chan TestExecutorEvent, stopRequest <-chan struct{}) {
defer log.Printf("[comm] handleConnection() returning..\n")
- defer func(){ eventChannel <- EventExecutionFinished{} }()
type received struct {
msg Message
@@ -170,6 +180,8 @@
}
}
+ var finishStatus ExecStatusCode
+
// Handle connection.
linkLoop:
for {
@@ -187,10 +199,12 @@
err := received.err
if err == io.EOF {
link.appendCommLogLine("Remote host closed connection")
+ finishStatus = EXEC_STATUS_DONE
break linkLoop
} else if err != nil {
log.Printf("[comm] GOT ERROR FROM READER: %s\n", err)
link.appendCommLogLine("Comm link terminating")
+ finishStatus = EXEC_STATUS_LINK_ERROR
break linkLoop
} else {
// Handle incoming messages.
@@ -239,11 +253,13 @@
if timeoutDiff >= KEEP_ALIVE_TIMEOUT_MINUTES * time.Minute {
link.appendCommLogLine("Client timeout")
// \todo[petri] handle timeout properly
+ finishStatus = EXEC_STATUS_TIMEOUT
break linkLoop
}
if isStopRequested && time.Now().Sub(firstStopRequestArrival) >= STOP_REQUEST_TIMEOUT_SECONDS * time.Second {
link.appendCommLogLine("Stop request timeout")
+ finishStatus = EXEC_STATUS_TIMEOUT
break linkLoop
}
@@ -254,6 +270,7 @@
msgKeepAlive := MsgKeepAlive{}
err := WriteMessage(conn, &msgKeepAlive)
if err != nil {
+ finishStatus = EXEC_STATUS_LINK_ERROR
break linkLoop
}
lastKeepaliveSent = time.Now()
@@ -265,6 +282,7 @@
err := WriteMessage(conn, &MsgStopExecution{})
if err != nil {
link.appendCommLogLine(fmt.Sprintf("Got error when sending stop command: %s", err))
+ finishStatus = EXEC_STATUS_LINK_ERROR
break linkLoop
}
isStopExecMsgPending = false
@@ -277,6 +295,8 @@
qpaParser.Terminate()
handleParserQueue()
}
+
+ eventChannel <- EventExecutionFinished{ finishStatus }
}
func (link *CommLinkTcpIp) Start () error {
diff --git a/cherry/testrunner.go b/cherry/testrunner.go
index 668afc7..351db92 100644
--- a/cherry/testrunner.go
+++ b/cherry/testrunner.go
@@ -258,6 +258,15 @@
// Execute a batch that has been initialized - i.e., the batch result and its test result objects have already been created and set to pending or other suitable status.
func (runner *TestRunner) executeBatch (batchResultId string, batchParams BatchExecParams, testCasePaths []string, stopRequest <-chan struct{}, executionLogAppend chan<- string) {
+
+ type BatchExecutionStatus int
+ const (
+ BATCH_EXEC_STATUS_RUNNING BatchExecutionStatus = iota
+ BATCH_EXEC_STATUS_DONE
+ BATCH_EXEC_STATUS_LINK_ERROR
+ BATCH_EXEC_STATUS_GENERIC_ERROR
+ )
+
// Start running batch result.
{
@@ -320,6 +329,7 @@
testPackage := runner.testPackages[packageName]
didProgress := false
+ var executionStatus BatchExecutionStatus = BATCH_EXEC_STATUS_RUNNING
// Try a few times (in case of connection errors).
for tryNdx := 0; tryNdx < 3; tryNdx++ {
@@ -328,6 +338,16 @@
time.Sleep((time.Duration)(tryNdx) * 500 * time.Millisecond)
}
+ // If previous error was link error, relaunch execserver just to be sure
+ if executionStatus == BATCH_EXEC_STATUS_LINK_ERROR && deviceConfig.IsADBDevice {
+ appendRunnerLogLine("Relaunching execserver")
+ err := RelaunchAndroidExecServer(deviceConfig.ADBSerialNumber)
+ if err != nil {
+ appendRunnerLogLine(fmt.Sprintf("Failed to relaunch ExecServer on Android via ADB: %v", err))
+ continue // Just try again, if tries left
+ }
+ }
+
// Create link to target.
linkParams := CommLinkParams {
SpawnProcessPath: batchParams.SpawnLocalProcess,
@@ -360,7 +380,8 @@
currentlyRunningCases := make(map[string]bool) // Paths of the test cases currently running.
// Handle all events from comm link, as well as stop requests.
- for executing := true; executing; {
+ executionStatus = BATCH_EXEC_STATUS_RUNNING
+ for executionStatus == BATCH_EXEC_STATUS_RUNNING {
select {
case <-stopRequest:
runCanceled = true
@@ -415,11 +436,21 @@
case EventProcessLaunchFailed:
launchFailed := event.(EventProcessLaunchFailed)
appendRunnerLogLine(fmt.Sprintf("Process launch failed: %s", launchFailed.reason))
- executing = false
+ executionStatus = BATCH_EXEC_STATUS_GENERIC_ERROR
case EventExecutionFinished:
- appendRunnerLogLine("Test execution finished")
- executing = false
+ appendRunnerLogLine(fmt.Sprintf("Test execution finished with status %#v", event.(EventExecutionFinished).status))
+ switch (event.(EventExecutionFinished).status) {
+ case EXEC_STATUS_DONE:
+ executionStatus = BATCH_EXEC_STATUS_DONE
+ case EXEC_STATUS_LINK_ERROR:
+ executionStatus = BATCH_EXEC_STATUS_LINK_ERROR
+ case EXEC_STATUS_TIMEOUT:
+ executionStatus = BATCH_EXEC_STATUS_GENERIC_ERROR
+ default:
+ appendRunnerLogLine(fmt.Sprintf("WARNING: unknown end status received: %#v", event.(EventExecutionFinished).status))
+ executionStatus = BATCH_EXEC_STATUS_GENERIC_ERROR
+ }
default:
appendRunnerLogLine(fmt.Sprintf("WARNING: unknown execute event received: %#v", event))