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 |