| OLD | NEW | 
|---|
| 1 # Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 1 # Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
| 2 # for details. All rights reserved. Use of this source code is governed by a | 2 # for details. All rights reserved. Use of this source code is governed by a | 
| 3 # BSD-style license that can be found in the LICENSE file. | 3 # BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 # This file contains a set of utilities functions used by other Python-based | 5 # This file contains a set of utilities functions used by other Python-based | 
| 6 # scripts. | 6 # scripts. | 
| 7 | 7 | 
| 8 import commands | 8 import commands | 
| 9 import contextlib | 9 import contextlib | 
| 10 import datetime | 10 import datetime | 
| (...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 693     os.chdir(self._old_cwd) | 693     os.chdir(self._old_cwd) | 
| 694 | 694 | 
| 695 | 695 | 
| 696 class UnexpectedCrash(object): | 696 class UnexpectedCrash(object): | 
| 697   def __init__(self, test, pid, binary): | 697   def __init__(self, test, pid, binary): | 
| 698     self.test = test | 698     self.test = test | 
| 699     self.pid = pid | 699     self.pid = pid | 
| 700     self.binary = binary | 700     self.binary = binary | 
| 701 | 701 | 
| 702   def __str__(self): | 702   def __str__(self): | 
| 703     return "%s: %s %s" % (self.test, self.binary, self.pid) | 703     return "Crash(%s: %s %s)" % (self.test, self.binary, self.pid) | 
| 704 | 704 | 
| 705 class SiteConfigBotoFileDisabler(object): | 705 class SiteConfigBotoFileDisabler(object): | 
| 706   def __init__(self): | 706   def __init__(self): | 
| 707     self._old_aws = None | 707     self._old_aws = None | 
| 708     self._old_boto = None | 708     self._old_boto = None | 
| 709 | 709 | 
| 710   def __enter__(self): | 710   def __enter__(self): | 
| 711     self._old_aws = os.environ.get('AWS_CREDENTIAL_FILE', None) | 711     self._old_aws = os.environ.get('AWS_CREDENTIAL_FILE', None) | 
| 712     self._old_boto = os.environ.get('BOTO_CONFIG', None) | 712     self._old_boto = os.environ.get('BOTO_CONFIG', None) | 
| 713 | 713 | 
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 824 | 824 | 
| 825 class BaseCoreDumpArchiver(object): | 825 class BaseCoreDumpArchiver(object): | 
| 826   """This class reads coredumps file written by UnexpectedCrashDumpArchiver | 826   """This class reads coredumps file written by UnexpectedCrashDumpArchiver | 
| 827   into the current working directory and uploads all cores and binaries | 827   into the current working directory and uploads all cores and binaries | 
| 828   listed in it into Cloud Storage (see tools/testing/dart/test_progress.dart). | 828   listed in it into Cloud Storage (see tools/testing/dart/test_progress.dart). | 
| 829   """ | 829   """ | 
| 830 | 830 | 
| 831   # test.dart will write a line for each unexpected crash into this file. | 831   # test.dart will write a line for each unexpected crash into this file. | 
| 832   _UNEXPECTED_CRASHES_FILE = "unexpected-crashes" | 832   _UNEXPECTED_CRASHES_FILE = "unexpected-crashes" | 
| 833 | 833 | 
| 834   def __init__(self): | 834   def __init__(self, search_dir): | 
| 835     self._bucket = 'dart-temp-crash-archive' | 835     self._bucket = 'dart-temp-crash-archive' | 
| 836     self._binaries_dir = os.getcwd() | 836     self._binaries_dir = os.getcwd() | 
|  | 837     self._search_dir = search_dir | 
| 837 | 838 | 
| 838   def __enter__(self): | 839   def __enter__(self): | 
| 839     # Cleanup any stale files | 840     # Cleanup any stale files | 
| 840     if self._cleanup(): | 841     if self._cleanup(): | 
| 841       print "WARNING: Found and removed stale coredumps" | 842       print "WARNING: Found and removed stale coredumps" | 
| 842 | 843 | 
| 843   def __exit__(self, *_): | 844   def __exit__(self, *_): | 
| 844     try: | 845     try: | 
| 845       crashes = self._find_unexpected_crashes() | 846       crashes = self._find_unexpected_crashes() | 
| 846       if crashes: | 847       if crashes: | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 864     files = set() | 865     files = set() | 
| 865     missing = [] | 866     missing = [] | 
| 866     for crash in crashes: | 867     for crash in crashes: | 
| 867       files.add(crash.binary) | 868       files.add(crash.binary) | 
| 868       core = self._find_coredump_file(crash) | 869       core = self._find_coredump_file(crash) | 
| 869       if core: | 870       if core: | 
| 870         files.add(core) | 871         files.add(core) | 
| 871       else: | 872       else: | 
| 872         missing.append(crash) | 873         missing.append(crash) | 
| 873     self._upload(files) | 874     self._upload(files) | 
|  | 875 | 
| 874     if missing: | 876     if missing: | 
| 875       raise Exception('Missing crash dumps for: %s' % ', '.join( | 877       self._report_missing_crashes(missing, throw=True) | 
| 876           [str(c) for c in missing])) | 878 | 
|  | 879   def _report_missing_crashes(self, missing, throw=True): | 
|  | 880     missing_as_string = ', '.join([str(c) for c in missing]) | 
|  | 881     other_files = list(glob.glob(os.path.join(self._search_dir, '*'))) | 
|  | 882     print >> sys.stderr, ( | 
|  | 883         "Could not find crash dumps for '%s' in search directory '%s'.\n" | 
|  | 884         "Existing files which *did not* match the pattern inside the search " | 
|  | 885         "directory are are:\n  %s" | 
|  | 886         % (missing_as_string, self._search_dir, '\n  '.join(other_files))) | 
|  | 887     if throw: | 
|  | 888       raise Exception('Missing crash dumps for: %s' % missing_as_string) | 
| 877 | 889 | 
| 878   def _upload(self, files): | 890   def _upload(self, files): | 
| 879     bot_utils = GetBotUtils() | 891     bot_utils = GetBotUtils() | 
| 880     gsutil = bot_utils.GSUtil() | 892     gsutil = bot_utils.GSUtil() | 
| 881     storage_path = '%s/%s/' % (self._bucket, uuid.uuid4()) | 893     storage_path = '%s/%s/' % (self._bucket, uuid.uuid4()) | 
| 882     gs_prefix = 'gs://%s' % storage_path | 894     gs_prefix = 'gs://%s' % storage_path | 
| 883     http_prefix = 'https://storage.cloud.google.com/%s' % storage_path | 895     http_prefix = 'https://storage.cloud.google.com/%s' % storage_path | 
| 884 | 896 | 
| 885     print '\n--- Uploading into %s (%s) ---' % (gs_prefix, http_prefix) | 897     print '\n--- Uploading into %s (%s) ---' % (gs_prefix, http_prefix) | 
| 886     for file in files: | 898     for file in files: | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 927     if os.path.exists(BaseCoreDumpArchiver._UNEXPECTED_CRASHES_FILE): | 939     if os.path.exists(BaseCoreDumpArchiver._UNEXPECTED_CRASHES_FILE): | 
| 928       os.unlink(BaseCoreDumpArchiver._UNEXPECTED_CRASHES_FILE) | 940       os.unlink(BaseCoreDumpArchiver._UNEXPECTED_CRASHES_FILE) | 
| 929       found = True | 941       found = True | 
| 930     for binary in glob.glob(os.path.join(self._binaries_dir, 'binary.*')): | 942     for binary in glob.glob(os.path.join(self._binaries_dir, 'binary.*')): | 
| 931       found = True | 943       found = True | 
| 932       os.unlink(binary) | 944       os.unlink(binary) | 
| 933     return found | 945     return found | 
| 934 | 946 | 
| 935 class LinuxCoreDumpArchiver(BaseCoreDumpArchiver): | 947 class LinuxCoreDumpArchiver(BaseCoreDumpArchiver): | 
| 936   def __init__(self): | 948   def __init__(self): | 
| 937     super(self.__class__, self).__init__() | 949     super(self.__class__, self).__init__(os.getcwd()) | 
| 938     self._search_dir = os.getcwd() |  | 
| 939 | 950 | 
| 940   def _cleanup(self): | 951   def _cleanup(self): | 
| 941     found = super(self.__class__, self)._cleanup() | 952     found = super(self.__class__, self)._cleanup() | 
| 942     for core in glob.glob(os.path.join(self._search_dir, 'core.*')): | 953     for core in glob.glob(os.path.join(self._search_dir, 'core.*')): | 
| 943       found = True | 954       found = True | 
| 944       os.unlink(core) | 955       os.unlink(core) | 
| 945     return found | 956     return found | 
| 946 | 957 | 
| 947   def _find_coredump_file(self, crash): | 958   def _find_coredump_file(self, crash): | 
| 948     core_filename = os.path.join(self._search_dir, 'core.%s' % crash.pid) | 959     core_filename = os.path.join(self._search_dir, 'core.%s' % crash.pid) | 
| 949     if os.path.exists(core_filename): | 960     if os.path.exists(core_filename): | 
| 950       return core_filename | 961       return core_filename | 
| 951 | 962 | 
| 952 class WindowsCoreDumpArchiver(BaseCoreDumpArchiver): | 963 class WindowsCoreDumpArchiver(BaseCoreDumpArchiver): | 
| 953   def __init__(self): | 964   def __init__(self): | 
| 954     super(self.__class__, self).__init__() | 965     super(self.__class__, self).__init__(os.path.join( | 
| 955     self._search_dir = os.path.join( | 966         os.getcwd(), WindowsCoredumpEnabler.WINDOWS_COREDUMP_FOLDER)) | 
| 956         os.getcwd(), WindowsCoredumpEnabler.WINDOWS_COREDUMP_FOLDER) |  | 
| 957 | 967 | 
| 958   def _cleanup(self): | 968   def _cleanup(self): | 
| 959     found = super(self.__class__, self)._cleanup() | 969     found = super(self.__class__, self)._cleanup() | 
| 960     for core in glob.glob(os.path.join(self._search_dir, '*')): | 970     for core in glob.glob(os.path.join(self._search_dir, '*')): | 
| 961       found = True | 971       found = True | 
| 962       os.unlink(core) | 972       os.unlink(core) | 
| 963     return found | 973     return found | 
| 964 | 974 | 
| 965   def _find_coredump_file(self, crash): | 975   def _find_coredump_file(self, crash): | 
| 966     pattern = os.path.join(self._search_dir, '*.%s.*' % crash.pid) | 976     pattern = os.path.join(self._search_dir, '*.%s.*' % crash.pid) | 
| 967     for core_filename in glob.glob(pattern): | 977     for core_filename in glob.glob(pattern): | 
| 968       return core_filename | 978       return core_filename | 
| 969 | 979 | 
|  | 980   def _report_missing_crashes(self, missing, throw=True): | 
|  | 981     # Let's only print the debugging information and not throw. We'll do more | 
|  | 982     # validation for werfault.exe and throw afterwards. | 
|  | 983     super(self.__class__, self)._report_missing_crashes(missing, throw=False) | 
|  | 984 | 
|  | 985     # Let's check again for the image execution options for werfault. Maybe | 
|  | 986     # puppet came a long during testing and reverted our change. | 
|  | 987     try: | 
|  | 988       import winreg | 
|  | 989     except ImportError: | 
|  | 990       import _winreg as winreg | 
|  | 991     for wowbit in [winreg.KEY_WOW64_64KEY, winreg.KEY_WOW64_32KEY]: | 
|  | 992       try: | 
|  | 993          with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, | 
|  | 994                              WindowsCoredumpEnabler.IMGEXEC_NAME, | 
|  | 995                              0, | 
|  | 996                              winreg.KEY_READ | wowbit) as handle: | 
|  | 997           raise Exception( | 
|  | 998               "Found werfault.exe was disabled. Probably by puppet. Too bad") | 
|  | 999       except OSError: | 
|  | 1000         # If the open did not work the werfault.exe execution setting is as it | 
|  | 1001         # should be. | 
|  | 1002         pass | 
|  | 1003 | 
|  | 1004     if throw: | 
|  | 1005       missing_as_string = ', '.join([str(c) for c in missing]) | 
|  | 1006       raise Exception('Missing crash dumps for: %s' % missing_as_string) | 
|  | 1007 | 
| 970 @contextlib.contextmanager | 1008 @contextlib.contextmanager | 
| 971 def NooptCoreDumpArchiver(): | 1009 def NooptCoreDumpArchiver(): | 
| 972   yield | 1010   yield | 
| 973 | 1011 | 
| 974 | 1012 | 
| 975 def CoreDumpArchiver(args): | 1013 def CoreDumpArchiver(args): | 
| 976   enabled = '--copy-coredumps' in args | 1014   enabled = '--copy-coredumps' in args | 
| 977 | 1015 | 
| 978   if not enabled: | 1016   if not enabled: | 
| 979     return NooptCoreDumpArchiver() | 1017     return NooptCoreDumpArchiver() | 
| 980 | 1018 | 
| 981   osname = GuessOS() | 1019   osname = GuessOS() | 
| 982   if osname == 'linux': | 1020   if osname == 'linux': | 
| 983     return contextlib.nested(PosixCoredumpEnabler(), | 1021     return contextlib.nested(PosixCoredumpEnabler(), | 
| 984                              LinuxCoreDumpArchiver()) | 1022                              LinuxCoreDumpArchiver()) | 
| 985   elif osname == 'win32': | 1023   elif osname == 'win32': | 
| 986     return contextlib.nested(WindowsCoredumpEnabler(), | 1024     return contextlib.nested(WindowsCoredumpEnabler(), | 
| 987                              WindowsCoreDumpArchiver()) | 1025                              WindowsCoreDumpArchiver()) | 
| 988   else: | 1026   else: | 
| 989     # We don't have support for MacOS yet. | 1027     # We don't have support for MacOS yet. | 
| 990     assert osname == 'macos' | 1028     assert osname == 'macos' | 
| 991     return NooptCoreDumpArchiver() | 1029     return NooptCoreDumpArchiver() | 
| 992 | 1030 | 
| 993 if __name__ == "__main__": | 1031 if __name__ == "__main__": | 
| 994   import sys | 1032   import sys | 
| 995   Main() | 1033   Main() | 
| OLD | NEW | 
|---|