| OLD | NEW |
| 1 #!/bin/env python | 1 #!/bin/env python |
| 2 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # common.py | 6 # common.py |
| 7 | 7 |
| 8 """ Common code used by purify_test.py and quantify_test.py in order to automate | 8 """ Common code used by purify_test.py and quantify_test.py in order to automate |
| 9 running of Rational Purify and Quantify in a consistent manner. | 9 running of Rational Purify and Quantify in a consistent manner. |
| 10 """ | 10 """ |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 | 51 |
| 52 def _print_line(line, flush=True): | 52 def _print_line(line, flush=True): |
| 53 # Printing to a text file (including stdout) on Windows always winds up | 53 # Printing to a text file (including stdout) on Windows always winds up |
| 54 # using \r\n automatically. On buildbot, this winds up being read by a master | 54 # using \r\n automatically. On buildbot, this winds up being read by a master |
| 55 # running on Linux, so we manually convert crlf to '\n' | 55 # running on Linux, so we manually convert crlf to '\n' |
| 56 print line.rstrip() + '\n', | 56 print line.rstrip() + '\n', |
| 57 if flush: | 57 if flush: |
| 58 sys.stdout.flush() | 58 sys.stdout.flush() |
| 59 | 59 |
| 60 def RunSubprocess(proc, timeout=0, detach=False): | 60 def RunSubprocess(proc, timeout=0, detach=False): |
| 61 """ Runs a subprocess, polling every .2 seconds until it finishes or until | 61 """ Runs a subprocess, until it finishes or |timeout| is exceeded and the |
| 62 timeout is reached. Then kills the process with taskkill. A timeout <= 0 | 62 process is killed with taskkill. A |timeout| <= 0 means no timeout. |
| 63 means no timeout. | |
| 64 | 63 |
| 65 Args: | 64 Args: |
| 66 proc: list of process components (exe + args) | 65 proc: list of process components (exe + args) |
| 67 timeout: how long to wait before killing, <= 0 means wait forever | 66 timeout: how long to wait before killing, <= 0 means wait forever |
| 68 detach: Whether to pass the DETACHED_PROCESS argument to CreateProcess | 67 detach: Whether to pass the DETACHED_PROCESS argument to CreateProcess |
| 69 on Windows. This is used by Purify subprocesses on buildbot which | 68 on Windows. This is used by Purify subprocesses on buildbot which |
| 70 seem to get confused by the parent console that buildbot sets up. | 69 seem to get confused by the parent console that buildbot sets up. |
| 71 """ | 70 """ |
| 72 logging.info("running %s" % (" ".join(proc))) | 71 logging.info("running %s" % (" ".join(proc))) |
| 73 if detach: | 72 if detach: |
| 74 # see MSDN docs for "Process Creation Flags" | 73 # see MSDN docs for "Process Creation Flags" |
| 75 DETACHED_PROCESS = 0x8 | 74 DETACHED_PROCESS = 0x8 |
| 76 p = subprocess.Popen(proc, creationflags=DETACHED_PROCESS) | 75 p = subprocess.Popen(proc, creationflags=DETACHED_PROCESS) |
| 77 else: | 76 else: |
| 78 # For non-detached processes, manually read and print out stdout and stderr. | 77 # For non-detached processes, manually read and print out stdout and stderr. |
| 79 # By default, the subprocess is supposed to inherit these from its parent, | 78 # By default, the subprocess is supposed to inherit these from its parent, |
| 80 # however when run under buildbot, it seems unable to read data from a | 79 # however when run under buildbot, it seems unable to read data from a |
| 81 # grandchild process, so we have to read the child and print the data as if | 80 # grandchild process, so we have to read the child and print the data as if |
| 82 # it came from us for buildbot to read it. We're not sure why this is | 81 # it came from us for buildbot to read it. We're not sure why this is |
| 83 # necessary. | 82 # necessary. |
| 84 # TODO(erikkay): should we buffer stderr and stdout separately? | 83 # TODO(erikkay): should we buffer stderr and stdout separately? |
| 85 p = subprocess.Popen(proc, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 84 p = subprocess.Popen(proc, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 86 if timeout <= 0: | 85 |
| 87 while p.poll() is None: | 86 # How long to wait (in seconds) before printing progress log messages. |
| 88 if not detach: | 87 progress_delay = 300 |
| 88 progress_delay_time = time.time() + progress_delay |
| 89 did_timeout = False |
| 90 if timeout > 0: |
| 91 wait_until = time.time() + timeout |
| 92 while p.poll() is None and not did_timeout: |
| 93 if not detach: |
| 94 line = p.stdout.readline() |
| 95 while line: |
| 96 _print_line(line) |
| 89 line = p.stdout.readline() | 97 line = p.stdout.readline() |
| 90 while line: | 98 else: |
| 91 _print_line(line) | 99 # When we detach, blocking on reading stdout doesn't work, so we sleep |
| 92 line = p.stdout.readline() | 100 # a short time and poll. |
| 93 time.sleep(0.2) | 101 time.sleep(0.5) |
| 94 else: | 102 if time.time() >= progress_delay_time: |
| 95 wait_until = time.time() + timeout | 103 # Force output on a periodic basis to avoid getting killed off by the |
| 96 while p.poll() is None and time.time() < wait_until: | 104 # buildbot. |
| 97 if not detach: | 105 # TODO(erikkay): I'd prefer a less obtrusive 'print ".",' with a flush |
| 98 line = p.stdout.readline() | 106 # but because of how we're doing subprocesses, this doesn't appear to |
| 99 while line: | 107 # work reliably. |
| 100 _print_line(line) | 108 logging.info("%s still running..." % os.path.basename(proc[0])) |
| 101 line = p.stdout.readline() | 109 progress_delay_time = time.time() + progress_delay |
| 102 time.sleep(0.2) | 110 if timeout > 0: |
| 103 if not detach: | 111 did_timeout = time.time() > wait_until |
| 112 |
| 113 if did_timeout: |
| 114 subprocess.call(["taskkill", "/T", "/F", "/PID", str(p.pid)]) |
| 115 logging.error("KILLED %d" % p.pid) |
| 116 # Give the process a chance to actually die before continuing |
| 117 # so that cleanup can happen safely. |
| 118 time.sleep(1.0) |
| 119 logging.error("TIMEOUT waiting for %s" % proc[0]) |
| 120 raise TimeoutError(proc[0]) |
| 121 elif not detach: |
| 104 for line in p.stdout.readlines(): | 122 for line in p.stdout.readlines(): |
| 105 _print_line(line, False) | 123 _print_line(line, False) |
| 106 p.stdout.flush() | 124 p.stdout.flush() |
| 125 |
| 107 result = p.poll() | 126 result = p.poll() |
| 108 if result is None: | |
| 109 subprocess.call(["taskkill", "/T", "/F", "/PID", str(p.pid)]) | |
| 110 logging.error("KILLED %d" % p.pid) | |
| 111 # give the process a chance to actually die before continuing | |
| 112 # so that cleanup can happen safely | |
| 113 time.sleep(1.0) | |
| 114 logging.error("TIMEOUT waiting for %s" % proc[0]) | |
| 115 raise TimeoutError(proc[0]) | |
| 116 if result: | 127 if result: |
| 117 logging.error("%s exited with non-zero result code %d" % (proc[0], result)) | 128 logging.error("%s exited with non-zero result code %d" % (proc[0], result)) |
| 118 return result | 129 return result |
| 119 | 130 |
| 120 | 131 |
| 121 def FixPath(path): | 132 def FixPath(path): |
| 122 """We pass computed paths to Rational as arguments, so these paths must be | 133 """We pass computed paths to Rational as arguments, so these paths must be |
| 123 valid windows paths. When running in cygwin's python, computed paths | 134 valid windows paths. When running in cygwin's python, computed paths |
| 124 wind up looking like /cygdrive/c/..., so we need to call out to cygpath | 135 wind up looking like /cygdrive/c/..., so we need to call out to cygpath |
| 125 to fix them up. | 136 to fix them up. |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 file = os.path.join(self._cache_dir, cfile); | 318 file = os.path.join(self._cache_dir, cfile); |
| 308 if os.path.isfile(file): | 319 if os.path.isfile(file): |
| 309 try: | 320 try: |
| 310 os.remove(file) | 321 os.remove(file) |
| 311 except: | 322 except: |
| 312 logging.warning("unable to delete file %s: %s" % (file, | 323 logging.warning("unable to delete file %s: %s" % (file, |
| 313 sys.exc_info()[0])) | 324 sys.exc_info()[0])) |
| 314 | 325 |
| 315 | 326 |
| 316 | 327 |
| OLD | NEW |