Chromium Code Reviews| 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 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 715 del os.environ['AWS_CREDENTIAL_FILE'] | 715 del os.environ['AWS_CREDENTIAL_FILE'] |
| 716 if self._old_boto: | 716 if self._old_boto: |
| 717 del os.environ['BOTO_CONFIG'] | 717 del os.environ['BOTO_CONFIG'] |
| 718 | 718 |
| 719 def __exit__(self, *_): | 719 def __exit__(self, *_): |
| 720 if self._old_aws: | 720 if self._old_aws: |
| 721 os.environ['AWS_CREDENTIAL_FILE'] = self._old_aws | 721 os.environ['AWS_CREDENTIAL_FILE'] = self._old_aws |
| 722 if self._old_boto: | 722 if self._old_boto: |
| 723 os.environ['BOTO_CONFIG'] = self._old_boto | 723 os.environ['BOTO_CONFIG'] = self._old_boto |
| 724 | 724 |
| 725 class PosixCoredumpEnabler(object): | 725 class PosixCoreDumpEnabler(object): |
| 726 def __init__(self): | 726 def __init__(self): |
| 727 self._old_limits = None | 727 self._old_limits = None |
| 728 | 728 |
| 729 def __enter__(self): | 729 def __enter__(self): |
| 730 self._old_limits = resource.getrlimit(resource.RLIMIT_CORE) | 730 self._old_limits = resource.getrlimit(resource.RLIMIT_CORE) |
| 731 | 731 resource.setrlimit(resource.RLIMIT_CORE, (-1, -1)) |
| 732 # Bump core limits to unlimited if core_pattern is correctly configured. | |
| 733 if CheckLinuxCoreDumpPattern(fatal=False): | |
| 734 resource.setrlimit(resource.RLIMIT_CORE, (-1, -1)) | |
| 735 | 732 |
| 736 def __exit__(self, *_): | 733 def __exit__(self, *_): |
| 737 resource.setrlimit(resource.RLIMIT_CORE, self._old_limits) | 734 resource.setrlimit(resource.RLIMIT_CORE, self._old_limits) |
| 735 | |
| 736 class LinuxCoreDumpEnabler(PosixCoreDumpEnabler): | |
| 737 def __enter__(self): | |
| 738 # Bump core limits to unlimited if core_pattern is correctly configured. | |
| 739 if CheckLinuxCoreDumpPattern(fatal=False): | |
| 740 super(LinuxCoreDumpEnabler, self).__enter__() | |
| 741 | |
| 742 def __exit__(self, *args): | |
| 738 CheckLinuxCoreDumpPattern(fatal=True) | 743 CheckLinuxCoreDumpPattern(fatal=True) |
| 744 super(LinuxCoreDumpEnabler, self).__exit__(*args) | |
| 739 | 745 |
| 740 class WindowsCoredumpEnabler(object): | 746 class WindowsCoreDumpEnabler(object): |
| 741 """Configure Windows Error Reporting to store crash dumps. | 747 """Configure Windows Error Reporting to store crash dumps. |
| 742 | 748 |
| 743 The documentation can be found here: | 749 The documentation can be found here: |
| 744 https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181.aspx | 750 https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181.aspx |
| 745 """ | 751 """ |
| 746 | 752 |
| 747 WINDOWS_COREDUMP_FOLDER = r'crashes' | 753 WINDOWS_COREDUMP_FOLDER = r'crashes' |
| 748 | 754 |
| 749 WER_NAME = r'SOFTWARE\Microsoft\Windows\Windows Error Reporting' | 755 WER_NAME = r'SOFTWARE\Microsoft\Windows\Windows Error Reporting' |
| 750 WER_LOCALDUMPS_NAME = r'%s\LocalDumps' % WER_NAME | 756 WER_LOCALDUMPS_NAME = r'%s\LocalDumps' % WER_NAME |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 773 self.winreg.KEY_ALL_ACCESS | sam) as wer: | 779 self.winreg.KEY_ALL_ACCESS | sam) as wer: |
| 774 with self.winreg.CreateKeyEx( | 780 with self.winreg.CreateKeyEx( |
| 775 self.winreg.HKEY_LOCAL_MACHINE, self.WER_LOCALDUMPS_NAME, 0, | 781 self.winreg.HKEY_LOCAL_MACHINE, self.WER_LOCALDUMPS_NAME, 0, |
| 776 self.winreg.KEY_ALL_ACCESS | sam) as wer_localdumps: | 782 self.winreg.KEY_ALL_ACCESS | sam) as wer_localdumps: |
| 777 # Prevent any modal UI dialog & disable normal windows error reporting | 783 # Prevent any modal UI dialog & disable normal windows error reporting |
| 778 # TODO(kustermann): Remove this once https://crbug.com/691971 is fixed | 784 # TODO(kustermann): Remove this once https://crbug.com/691971 is fixed |
| 779 self.winreg.SetValueEx(wer, "DontShowUI", 0, self.winreg.REG_DWORD, 1) | 785 self.winreg.SetValueEx(wer, "DontShowUI", 0, self.winreg.REG_DWORD, 1) |
| 780 self.winreg.SetValueEx(wer, "Disabled", 0, self.winreg.REG_DWORD, 1) | 786 self.winreg.SetValueEx(wer, "Disabled", 0, self.winreg.REG_DWORD, 1) |
| 781 | 787 |
| 782 coredump_folder = os.path.join( | 788 coredump_folder = os.path.join( |
| 783 os.getcwd(), WindowsCoredumpEnabler.WINDOWS_COREDUMP_FOLDER) | 789 os.getcwd(), WindowsCoreDumpEnabler.WINDOWS_COREDUMP_FOLDER) |
| 784 | 790 |
| 785 # Create the directory which will contain the dumps | 791 # Create the directory which will contain the dumps |
| 786 if not os.path.exists(coredump_folder): | 792 if not os.path.exists(coredump_folder): |
| 787 os.mkdir(coredump_folder) | 793 os.mkdir(coredump_folder) |
| 788 | 794 |
| 789 # Do full dumps (not just mini dumps), keep max 100 dumps and specify | 795 # Do full dumps (not just mini dumps), keep max 100 dumps and specify |
| 790 # folder. | 796 # folder. |
| 791 self.winreg.SetValueEx( | 797 self.winreg.SetValueEx( |
| 792 wer_localdumps, "DumpType", 0, self.winreg.REG_DWORD, 2) | 798 wer_localdumps, "DumpType", 0, self.winreg.REG_DWORD, 2) |
| 793 self.winreg.SetValueEx( | 799 self.winreg.SetValueEx( |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 937 def _cleanup(self): | 943 def _cleanup(self): |
| 938 found = False | 944 found = False |
| 939 if os.path.exists(BaseCoreDumpArchiver._UNEXPECTED_CRASHES_FILE): | 945 if os.path.exists(BaseCoreDumpArchiver._UNEXPECTED_CRASHES_FILE): |
| 940 os.unlink(BaseCoreDumpArchiver._UNEXPECTED_CRASHES_FILE) | 946 os.unlink(BaseCoreDumpArchiver._UNEXPECTED_CRASHES_FILE) |
| 941 found = True | 947 found = True |
| 942 for binary in glob.glob(os.path.join(self._binaries_dir, 'binary.*')): | 948 for binary in glob.glob(os.path.join(self._binaries_dir, 'binary.*')): |
| 943 found = True | 949 found = True |
| 944 os.unlink(binary) | 950 os.unlink(binary) |
| 945 return found | 951 return found |
| 946 | 952 |
| 947 class LinuxCoreDumpArchiver(BaseCoreDumpArchiver): | 953 class PosixCoreDumpArchiver(BaseCoreDumpArchiver): |
| 948 def __init__(self): | 954 def __init__(self, search_dir): |
| 949 super(self.__class__, self).__init__(os.getcwd()) | 955 super(PosixCoreDumpArchiver, self).__init__(search_dir) |
| 950 | 956 |
| 951 def _cleanup(self): | 957 def _cleanup(self): |
| 952 found = super(self.__class__, self)._cleanup() | 958 found = super(PosixCoreDumpArchiver, self)._cleanup() |
| 953 for core in glob.glob(os.path.join(self._search_dir, 'core.*')): | 959 for core in glob.glob(os.path.join(self._search_dir, 'core.*')): |
| 954 found = True | 960 found = True |
| 955 os.unlink(core) | 961 os.unlink(core) |
|
Vyacheslav Egorov (Google)
2017/04/18 11:12:51
maybe wrap this in try: for MacOS case - because o
kustermann
2017/04/19 08:36:13
Done.
| |
| 956 return found | 962 return found |
| 957 | 963 |
| 958 def _find_coredump_file(self, crash): | 964 def _find_coredump_file(self, crash): |
| 959 core_filename = os.path.join(self._search_dir, 'core.%s' % crash.pid) | 965 core_filename = os.path.join(self._search_dir, 'core.%s' % crash.pid) |
| 960 if os.path.exists(core_filename): | 966 if os.path.exists(core_filename): |
| 961 return core_filename | 967 return core_filename |
| 962 | 968 |
| 969 class LinuxCoreDumpArchiver(PosixCoreDumpArchiver): | |
| 970 def __init__(self): | |
| 971 super(LinuxCoreDumpArchiver, self).__init__(os.getcwd()) | |
| 972 | |
| 973 class MacOSCoreDumpArchiver(PosixCoreDumpArchiver): | |
| 974 def __init__(self): | |
| 975 super(MacOSCoreDumpArchiver, self).__init__('/cores') | |
| 976 | |
| 963 class WindowsCoreDumpArchiver(BaseCoreDumpArchiver): | 977 class WindowsCoreDumpArchiver(BaseCoreDumpArchiver): |
| 964 def __init__(self): | 978 def __init__(self): |
| 965 super(self.__class__, self).__init__(os.path.join( | 979 super(WindowsCoreDumpArchiver, self).__init__(os.path.join( |
| 966 os.getcwd(), WindowsCoredumpEnabler.WINDOWS_COREDUMP_FOLDER)) | 980 os.getcwd(), WindowsCoreDumpEnabler.WINDOWS_COREDUMP_FOLDER)) |
| 967 | 981 |
| 968 def _cleanup(self): | 982 def _cleanup(self): |
| 969 found = super(self.__class__, self)._cleanup() | 983 found = super(WindowsCoreDumpArchiver, self)._cleanup() |
| 970 for core in glob.glob(os.path.join(self._search_dir, '*')): | 984 for core in glob.glob(os.path.join(self._search_dir, '*')): |
| 971 found = True | 985 found = True |
| 972 os.unlink(core) | 986 os.unlink(core) |
| 973 return found | 987 return found |
| 974 | 988 |
| 975 def _find_coredump_file(self, crash): | 989 def _find_coredump_file(self, crash): |
| 976 pattern = os.path.join(self._search_dir, '*.%s.*' % crash.pid) | 990 pattern = os.path.join(self._search_dir, '*.%s.*' % crash.pid) |
| 977 for core_filename in glob.glob(pattern): | 991 for core_filename in glob.glob(pattern): |
| 978 return core_filename | 992 return core_filename |
| 979 | 993 |
| 980 def _report_missing_crashes(self, missing, throw=True): | 994 def _report_missing_crashes(self, missing, throw=True): |
| 981 # Let's only print the debugging information and not throw. We'll do more | 995 # Let's only print the debugging information and not throw. We'll do more |
| 982 # validation for werfault.exe and throw afterwards. | 996 # validation for werfault.exe and throw afterwards. |
| 983 super(self.__class__, self)._report_missing_crashes(missing, throw=False) | 997 super(WindowsCoreDumpArchiver, self)._report_missing_crashes(missing, throw= False) |
| 984 | 998 |
| 985 # Let's check again for the image execution options for werfault. Maybe | 999 # Let's check again for the image execution options for werfault. Maybe |
| 986 # puppet came a long during testing and reverted our change. | 1000 # puppet came a long during testing and reverted our change. |
| 987 try: | 1001 try: |
| 988 import winreg | 1002 import winreg |
| 989 except ImportError: | 1003 except ImportError: |
| 990 import _winreg as winreg | 1004 import _winreg as winreg |
| 991 for wowbit in [winreg.KEY_WOW64_64KEY, winreg.KEY_WOW64_32KEY]: | 1005 for wowbit in [winreg.KEY_WOW64_64KEY, winreg.KEY_WOW64_32KEY]: |
| 992 try: | 1006 try: |
| 993 with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, | 1007 with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, |
| 994 WindowsCoredumpEnabler.IMGEXEC_NAME, | 1008 WindowsCoreDumpEnabler.IMGEXEC_NAME, |
| 995 0, | 1009 0, |
| 996 winreg.KEY_READ | wowbit) as handle: | 1010 winreg.KEY_READ | wowbit) as handle: |
| 997 raise Exception( | 1011 raise Exception( |
| 998 "Found werfault.exe was disabled. Probably by puppet. Too bad! " | 1012 "Found werfault.exe was disabled. Probably by puppet. Too bad! " |
| 999 "(For more information see https://crbug.com/691971)") | 1013 "(For more information see https://crbug.com/691971)") |
| 1000 except OSError: | 1014 except OSError: |
| 1001 # If the open did not work the werfault.exe execution setting is as it | 1015 # If the open did not work the werfault.exe execution setting is as it |
| 1002 # should be. | 1016 # should be. |
| 1003 pass | 1017 pass |
| 1004 | 1018 |
| 1005 if throw: | 1019 if throw: |
| 1006 missing_as_string = ', '.join([str(c) for c in missing]) | 1020 missing_as_string = ', '.join([str(c) for c in missing]) |
| 1007 raise Exception('Missing crash dumps for: %s' % missing_as_string) | 1021 raise Exception('Missing crash dumps for: %s' % missing_as_string) |
| 1008 | 1022 |
| 1009 @contextlib.contextmanager | 1023 @contextlib.contextmanager |
| 1010 def NooptCoreDumpArchiver(): | 1024 def NooptCoreDumpArchiver(): |
| 1011 yield | 1025 yield |
| 1012 | 1026 |
| 1013 | |
| 1014 def CoreDumpArchiver(args): | 1027 def CoreDumpArchiver(args): |
| 1015 enabled = '--copy-coredumps' in args | 1028 enabled = '--copy-coredumps' in args |
| 1016 | 1029 |
| 1017 if not enabled: | 1030 if not enabled: |
| 1018 return NooptCoreDumpArchiver() | 1031 return NooptCoreDumpArchiver() |
| 1019 | 1032 |
| 1020 osname = GuessOS() | 1033 osname = GuessOS() |
| 1021 if osname == 'linux': | 1034 if osname == 'linux': |
| 1022 return contextlib.nested(PosixCoredumpEnabler(), | 1035 return contextlib.nested(LinuxCoreDumpEnabler(), |
| 1023 LinuxCoreDumpArchiver()) | 1036 LinuxCoreDumpArchiver()) |
| 1037 elif osname == 'macos': | |
| 1038 return contextlib.nested(PosixCoreDumpEnabler(), | |
| 1039 MacOSCoreDumpArchiver()) | |
| 1024 elif osname == 'win32': | 1040 elif osname == 'win32': |
| 1025 return contextlib.nested(WindowsCoredumpEnabler(), | 1041 return contextlib.nested(WindowsCoreDumpEnabler(), |
| 1026 WindowsCoreDumpArchiver()) | 1042 WindowsCoreDumpArchiver()) |
| 1027 else: | 1043 else: |
| 1028 # We don't have support for MacOS yet. | 1044 # We don't have support for MacOS yet. |
| 1029 assert osname == 'macos' | 1045 assert osname == 'macos' |
| 1030 return NooptCoreDumpArchiver() | 1046 return NooptCoreDumpArchiver() |
| 1031 | 1047 |
| 1032 if __name__ == "__main__": | 1048 if __name__ == "__main__": |
| 1033 import sys | 1049 import sys |
| 1034 Main() | 1050 Main() |
| OLD | NEW |