Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: tools/utils.py

Issue 2644593002: Buildbot: Change --copy-crashdumps to do the actual archiving to CloudStorage. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 datetime 9 import datetime
10 import json 10 import json
11 import os 11 import os
12 import platform 12 import platform
13 import re 13 import re
14 import shutil 14 import shutil
15 import subprocess 15 import subprocess
16 import tempfile 16 import tempfile
17 import sys 17 import sys
18 import uuid
19
20 try:
21 import resource
22 import tarfile
23 from bots import bot_utils
24 from glob import glob
kustermann 2017/01/18 17:12:36 Does this need to be in the try?
Vyacheslav Egorov (Google) 2017/01/18 19:57:00 Done.
25 except:
26 pass
18 27
19 class Version(object): 28 class Version(object):
20 def __init__(self, channel, major, minor, patch, prerelease, 29 def __init__(self, channel, major, minor, patch, prerelease,
21 prerelease_patch): 30 prerelease_patch):
22 self.channel = channel 31 self.channel = channel
23 self.major = major 32 self.major = major
24 self.minor = minor 33 self.minor = minor
25 self.patch = patch 34 self.patch = patch
26 self.prerelease = prerelease 35 self.prerelease = prerelease
27 self.prerelease_patch = prerelease_patch 36 self.prerelease_patch = prerelease_patch
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 659
651 def __enter__(self): 660 def __enter__(self):
652 self._old_cwd = os.getcwd() 661 self._old_cwd = os.getcwd()
653 print "Enter directory = ", self._working_directory 662 print "Enter directory = ", self._working_directory
654 os.chdir(self._working_directory) 663 os.chdir(self._working_directory)
655 664
656 def __exit__(self, *_): 665 def __exit__(self, *_):
657 print "Enter directory = ", self._old_cwd 666 print "Enter directory = ", self._old_cwd
658 os.chdir(self._old_cwd) 667 os.chdir(self._old_cwd)
659 668
669 # This class finds and archives all core.* files from the current working
670 # directory and all binaries copied by UnexpectedCrashDumpArchiver into
kustermann 2017/01/18 17:12:35 add `(from tools/testing/dart/test_progress.dart)`
Vyacheslav Egorov (Google) 2017/01/18 19:57:00 Done.
671 # the current working directory.
672 class CoreDumpArchiver(object):
673 def __init__(self, args):
674 self._enabled = '--copy-coredumps' in args and GuessOS() == 'linux'
675 self._search_dir = os.getcwd()
676 self._bucket = 'dart-temp-crash-archive'
677 self._old_limits = None
678
679 def __enter__(self):
680 if not self._enabled:
681 return
682
683 # Cleanup any stale coredumps
684 coredumps = self._find_coredumps()
685 if coredumps:
686 print "WARNING: Found stale coredumps, removing"
687 MarkCurrentStepWarning()
688 self._remove_coredumps(coredumps)
689
690 self._old_limits = resource.getrlimit(resource.RLIMIT_CORE)
691
692 # Bump core limits to unlimited if core_pattern is correctly configured.
693 if self._check_core_dump_pattern(fatal=False):
694 resource.setrlimit(resource.RLIMIT_CORE, (-1, -1))
695
696 def __exit__(self, *_):
697 if not self._enabled:
698 return
699
700 # Restore old core limit.
701 resource.setrlimit(resource.RLIMIT_CORE, self._old_limits)
702
703 # Check that kernel was correctly configured to use core.%p
704 # core_pattern.
705 self._check_core_dump_pattern(fatal=True)
706
707 coredumps = self._find_coredumps()
708 if coredumps:
709 # If we get a ton of crashes, only archive 10 dumps.
710 archive_coredumps = coredumps[:10]
Bill Hesse 2017/01/24 16:01:21 Do we want to make sure the binaries are in archiv
Vyacheslav Egorov (Google) 2017/01/24 16:12:13 Nice catch Bill! Though we changed the way this c
711 print 'Archiving coredumps: %s' % ', '.join(archive_coredumps)
712 sys.stdout.flush()
713 self._archive(archive_coredumps)
714 self._remove_coredumps(coredumps)
715 coredumps = self._find_coredumps()
716 assert not coredumps
717
718 def _find_coredumps(self):
719 return glob(os.path.join(self._search_dir, 'core.*'))
720
721 def _remove_coredumps(self, coredumps):
722 for name in coredumps:
723 os.unlink(name)
724
725 def _archive(self, coredumps):
726 gsutil = bot_utils.GSUtil()
727 storage_path = '%s/%s/' % (self._bucket, uuid.uuid4())
728 gs_prefix = 'gs://%s' % storage_path
729 http_prefix = 'https://storage.cloud.google.com/%s' % storage_path
730
731 for core in coredumps:
732 # Sanitize the name: actual cores follow 'core.%d' pattern, crashed
733 # binaries are copied next to cores and named 'core.<binary_name>'.
734 suffix = os.path.basename(core).split('.')[1]
735 try:
736 # Check if suffix is an integer - in this case it's an actual core.
737 clean_name = 'core.%d' % int(suffix)
738 except:
739 # This is not a coredump but a crashed binary.
740 clean_name = suffix
741
742 tarname = '%s.tar.gz' % clean_name
743
744 # Create a .tar.gz archive out of a crash folder that contains
745 # both binary and the core dump.
746 tar = tarfile.open(tarname, mode='w:gz')
747 tar.add(core, arcname=clean_name)
748 tar.close()
kustermann 2017/01/18 17:12:35 Strictly speaking, we don't need .tar.gz we just n
Vyacheslav Egorov (Google) 2017/01/18 19:57:00 Acknowledged.
749
750 # Remove / from absolute path to not have // in gs path.
751 gs_url = '%s%s' % (gs_prefix, tarname.lstrip('/'))
752 http_url = '%s%s' % (http_prefix, tarname.lstrip('/'))
kustermann 2017/01/18 17:12:35 How could [tarname] ever contain a '/' ?
Vyacheslav Egorov (Google) 2017/01/18 19:57:00 Now it can't - it used to use an absolute path.
753
754 try:
755 gsutil.upload(tarname, gs_url)
756 print '@@@STEP_LOG_LINE@coredumps@%s (%s)@@@' % (gs_url, http_url)
757 except Exception as error:
758 message = "Failed to upload coredump %s, error: %s" % (tarname, error)
759 print '@@@STEP_LOG_LINE@coredumps@%s@@@' % message
760
761 os.unlink(tarname)
762
763 print '@@@STEP_LOG_END@coredumps@@@'
764 MarkCurrentStepWarning()
765
766 def _check_core_dump_pattern(self, fatal=False):
767 core_pattern_file = '/proc/sys/kernel/core_pattern'
768 core_pattern = open(core_pattern_file).read()
769
770 expected_core_pattern = 'core.%p'
771 if core_pattern.strip() != expected_core_pattern:
772 if fatal:
773 message = ("Invalid core_pattern configuration. "
774 "The configuration of core dump handling is *not* correct for "
775 "a buildbot. The content of {0} must be '{1}' instead of '{2}'."
776 .format(core_pattern_file, expected_core_pattern, core_pattern))
777 raise Exception(message)
778 else:
779 return False
780 return True
781
782 def MarkCurrentStepWarning():
783 print "@@@STEP_WARNINGS@@@"
784 sys.stdout.flush()
660 785
661 if __name__ == "__main__": 786 if __name__ == "__main__":
662 import sys 787 import sys
663 Main() 788 Main()
OLDNEW
« tools/testing/dart/test_progress.dart ('K') | « tools/testing/dart/test_progress.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698