[analyzer] SATest: Add an easy option to connect to docker for debugging
authorValeriy Savchenko <vsavchenko@apple.com>
Mon, 8 Jun 2020 09:49:31 +0000 (12:49 +0300)
committerValeriy Savchenko <vsavchenko@apple.com>
Thu, 25 Jun 2020 09:28:22 +0000 (12:28 +0300)
Summary:
Docker on its own has a pretty convenient way to run shell.
This method, however, requires target container to be currently running,
which is not a usual scenario for the test system.  For this purpose,
it is better to have a simple way to run the container, shell it, and
clean up at the end of it all.  New option `--shell` does exactly this.

Differential Revision: https://reviews.llvm.org/D81598

clang/utils/analyzer/SATest.py
clang/utils/analyzer/entrypoint.py

index b7bf628..fb2e031 100755 (executable)
@@ -108,8 +108,10 @@ def docker(parser, args):
 
     if args.build_image:
         docker_build_image()
+    elif args.shell:
+        docker_shell(args)
     else:
-        docker_run(args)
+        sys.exit(docker_run(args, ' '.join(args.rest)))
 
 
 def docker_build_image():
@@ -117,21 +119,40 @@ def docker_build_image():
                   shell=True))
 
 
-def docker_run(args):
-    sys.exit(call("docker run --rm --name satest "
-                  "-v {llvm}:/llvm-project "
-                  "-v {build}:/build "
-                  "-v {clang}:/analyzer "
-                  "-v {scripts}:/scripts "
-                  "-v {projects}:/projects "
-                  "satest-image:latest {args}"
-                  .format(llvm=args.llvm_project_dir,
-                          build=args.build_dir,
-                          clang=args.clang_dir,
-                          scripts=SCRIPTS_DIR,
-                          projects=PROJECTS_DIR,
-                          args=' '.join(args.rest)),
-                  shell=True))
+def docker_shell(args):
+    try:
+        # First we need to start the docker container in a waiting mode,
+        # so it doesn't do anything, but most importantly keeps working
+        # while the shell session is in progress.
+        docker_run(args, "--wait", "--detach")
+        # Since the docker container is running, we can actually connect to it
+        call("docker exec -it satest bash", shell=True)
+
+    except KeyboardInterrupt:
+        pass
+
+    finally:
+        print("Please wait for docker to clean up")
+        call("docker stop satest", shell=True)
+
+
+def docker_run(args, command, docker_args=""):
+    return call("docker run --rm --name satest "
+                "-v {llvm}:/llvm-project "
+                "-v {build}:/build "
+                "-v {clang}:/analyzer "
+                "-v {scripts}:/scripts "
+                "-v {projects}:/projects "
+                "{docker_args} "
+                "satest-image:latest {command}"
+                .format(llvm=args.llvm_project_dir,
+                        build=args.build_dir,
+                        clang=args.clang_dir,
+                        scripts=SCRIPTS_DIR,
+                        projects=PROJECTS_DIR,
+                        docker_args=docker_args,
+                        command=command),
+                shell=True)
 
 
 def main():
index 02eb5cb..b440e77 100644 (file)
@@ -2,13 +2,15 @@ import argparse
 import os
 import sys
 
-from typing import List, Tuple
-
 from subprocess import call, check_call, CalledProcessError
+from time import sleep
+from typing import List, Tuple
 
 
 def main():
     settings, rest = parse_arguments()
+    if settings.wait:
+        wait()
     if settings.build_llvm or settings.build_llvm_only:
         build_llvm()
     if settings.build_llvm_only:
@@ -16,8 +18,16 @@ def main():
     sys.exit(test(rest))
 
 
+def wait():
+    # It is an easy on CPU way of keeping the docker container running
+    # while the user has a terminal session in that container.
+    while True:
+        sleep(3600)
+
+
 def parse_arguments() -> Tuple[argparse.Namespace, List[str]]:
     parser = argparse.ArgumentParser()
+    parser.add_argument('--wait', action='store_true')
     parser.add_argument('--build-llvm', action='store_true')
     parser.add_argument('--build-llvm-only', action='store_true')
     return parser.parse_known_args()