]> Cypherpunks.ru repositories - gostls13.git/commitdiff
misc/ios: retry lldb launch if the iOS app is busy
authorElias Naur <elias.naur@gmail.com>
Thu, 3 May 2018 09:43:25 +0000 (11:43 +0200)
committerElias Naur <elias.naur@gmail.com>
Thu, 3 May 2018 15:23:13 +0000 (15:23 +0000)
Sometimes, a newly installed the test app is not ready to launch
or the reported app path is stale. Pause and retry the launch if
the lldb script did not run the program.

Change-Id: Ic7745d4b5a02f2e3cb8134341859039812f65a65
Reviewed-on: https://go-review.googlesource.com/111216
Run-TryBot: Elias Naur <elias.naur@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
misc/ios/go_darwin_arm_exec.go

index 675b8d26faa19bdab6b36a3ae46c3f6837d77b16..515bb8539cb805c3eeae19a0ca3736d42f5f418b 100644 (file)
@@ -129,11 +129,6 @@ func runMain() (int, error) {
                return 1, err
        }
 
-       deviceApp, err := findDeviceAppPath(bundleID)
-       if err != nil {
-               return 1, err
-       }
-
        if err := mountDevImage(); err != nil {
                return 1, err
        }
@@ -144,7 +139,7 @@ func runMain() (int, error) {
        }
        defer closer()
 
-       if err := run(appdir, deviceApp, os.Args[2:]); err != nil {
+       if err := run(appdir, bundleID, os.Args[2:]); err != nil {
                // If the lldb driver completed with an exit code, use that.
                if err, ok := err.(*exec.ExitError); ok {
                        if ws, ok := err.Sys().(interface{ ExitStatus() int }); ok {
@@ -408,14 +403,7 @@ func idevCmd(cmd *exec.Cmd) *exec.Cmd {
        return cmd
 }
 
-func run(appdir, deviceapp string, args []string) error {
-       lldb := exec.Command(
-               "python",
-               "-", // Read script from stdin.
-               appdir,
-               deviceapp,
-       )
-       lldb.Args = append(lldb.Args, args...)
+func run(appdir, bundleID string, args []string) error {
        var env []string
        for _, e := range os.Environ() {
                // Don't override TMPDIR on the device.
@@ -424,11 +412,39 @@ func run(appdir, deviceapp string, args []string) error {
                }
                env = append(env, e)
        }
-       lldb.Env = env
-       lldb.Stdin = strings.NewReader(lldbDriver)
-       lldb.Stdout = os.Stdout
-       lldb.Stderr = os.Stderr
-       return lldb.Run()
+       attempt := 0
+       for {
+               // The device app path is constant for a given installed app,
+               // but the device might not return a stale device path for
+               // a newly overwritten app, so retry the lookup as well.
+               deviceapp, err := findDeviceAppPath(bundleID)
+               if err != nil {
+                       return err
+               }
+               lldb := exec.Command(
+                       "python",
+                       "-", // Read script from stdin.
+                       appdir,
+                       deviceapp,
+               )
+               lldb.Args = append(lldb.Args, args...)
+               lldb.Env = env
+               lldb.Stdin = strings.NewReader(lldbDriver)
+               lldb.Stdout = os.Stdout
+               var out bytes.Buffer
+               lldb.Stderr = io.MultiWriter(&out, os.Stderr)
+               err = lldb.Run()
+               // If the program was not started it can be retried without papering over
+               // real test failures.
+               started := bytes.HasPrefix(out.Bytes(), []byte("lldb: running program"))
+               if started || err == nil || attempt == 5 {
+                       return err
+               }
+               // Sometimes, the app was not yet ready to launch or the device path was
+               // stale. Retry.
+               attempt++
+               time.Sleep(5 * time.Second)
+       }
 }
 
 func copyLocalDir(dst, src string) error {
@@ -665,22 +681,24 @@ for i in range(0, sigs.GetNumSignals()):
        sigs.SetShouldNotify(sig, False)
 
 event = lldb.SBEvent()
+running = False
 while True:
        if not listener.WaitForEvent(1, event):
                continue
        if not lldb.SBProcess.EventIsProcessEvent(event):
                continue
-       # Pass through stdout and stderr.
-       while True:
-               out = process.GetSTDOUT(8192)
-               if not out:
-                       break
-               sys.stdout.write(out)
-       while True:
-               out = process.GetSTDERR(8192)
-               if not out:
-                       break
-               sys.stderr.write(out)
+       if running:
+               # Pass through stdout and stderr.
+               while True:
+                       out = process.GetSTDOUT(8192)
+                       if not out:
+                               break
+                       sys.stdout.write(out)
+               while True:
+                       out = process.GetSTDERR(8192)
+                       if not out:
+                               break
+                       sys.stderr.write(out)
        state = process.GetStateFromEvent(event)
        if state in [lldb.eStateCrashed, lldb.eStateDetached, lldb.eStateUnloaded, lldb.eStateExited]:
                break
@@ -691,6 +709,9 @@ while True:
                        process.Kill()
                        debugger.Terminate()
                        sys.exit(1)
+               # Tell the Go driver that the program is running and should not be retried.
+               sys.stderr.write("lldb: running program\n")
+               running = True
                # Process stops once at the beginning. Continue.
                process.Continue()