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

Side by Side Diff: base/debug/activity_tracker.h

Issue 2702413006: Enable storing last-dispatched exception per-thread. (Closed)
Patch Set: removed user-data for exception tracking; keep it simple to start Created 3 years, 9 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
« no previous file with comments | « no previous file | base/debug/activity_tracker.cc » ('j') | base/debug/activity_tracker.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Activity tracking provides a low-overhead method of collecting information 5 // Activity tracking provides a low-overhead method of collecting information
6 // about the state of the application for analysis both while it is running 6 // about the state of the application for analysis both while it is running
7 // and after it has terminated unexpectedly. Its primary purpose is to help 7 // and after it has terminated unexpectedly. Its primary purpose is to help
8 // locate reasons the browser becomes unresponsive by providing insight into 8 // locate reasons the browser becomes unresponsive by providing insight into
9 // what all the various threads and processes are (or were) doing. 9 // what all the various threads and processes are (or were) doing.
10 10
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 uint32_t padding; 89 uint32_t padding;
90 int64_t process_id; 90 int64_t process_id;
91 int64_t create_stamp; 91 int64_t create_stamp;
92 }; 92 };
93 93
94 // The data associated with an activity is dependent upon the activity type. 94 // The data associated with an activity is dependent upon the activity type.
95 // This union defines all of the various fields. All fields must be explicitly 95 // This union defines all of the various fields. All fields must be explicitly
96 // sized types to ensure no interoperability problems between 32-bit and 96 // sized types to ensure no interoperability problems between 32-bit and
97 // 64-bit systems. 97 // 64-bit systems.
98 union ActivityData { 98 union ActivityData {
99 // Expected size for 32/64-bit check.
100 // TODO(bcwhite): VC2015 doesn't allow statics in unions. Fix when it does.
101 // static constexpr size_t kExpectedInstanceSize = 8;
102
99 // Generic activities don't have any defined structure. 103 // Generic activities don't have any defined structure.
100 struct { 104 struct {
101 uint32_t id; // An arbitrary identifier used for association. 105 uint32_t id; // An arbitrary identifier used for association.
102 int32_t info; // An arbitrary value used for information purposes. 106 int32_t info; // An arbitrary value used for information purposes.
103 } generic; 107 } generic;
104 struct { 108 struct {
105 uint64_t sequence_id; // The sequence identifier of the posted task. 109 uint64_t sequence_id; // The sequence identifier of the posted task.
106 } task; 110 } task;
107 struct { 111 struct {
108 uint64_t lock_address; // The memory address of the lock object. 112 uint64_t lock_address; // The memory address of the lock object.
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 // Thread activities involve the life management of threads. 269 // Thread activities involve the life management of threads.
266 ACT_THREAD = 4 << 4, 270 ACT_THREAD = 4 << 4,
267 ACT_THREAD_START = ACT_THREAD, 271 ACT_THREAD_START = ACT_THREAD,
268 ACT_THREAD_JOIN, 272 ACT_THREAD_JOIN,
269 273
270 // Process activities involve the life management of processes. 274 // Process activities involve the life management of processes.
271 ACT_PROCESS = 5 << 4, 275 ACT_PROCESS = 5 << 4,
272 ACT_PROCESS_START = ACT_PROCESS, 276 ACT_PROCESS_START = ACT_PROCESS,
273 ACT_PROCESS_WAIT, 277 ACT_PROCESS_WAIT,
274 278
279 // Exception activities indicate the occurence of something unexpected.
280 ACT_EXCEPTION = 14 << 4,
281
275 // Generic activities are user defined and can be anything. 282 // Generic activities are user defined and can be anything.
276 ACT_GENERIC = 15 << 4, 283 ACT_GENERIC = 15 << 4,
277 284
278 // These constants can be used to separate the category and action from 285 // These constants can be used to separate the category and action from
279 // a combined activity type. 286 // a combined activity type.
280 ACT_CATEGORY_MASK = 0xF << 4, 287 ACT_CATEGORY_MASK = 0xF << 4,
281 ACT_ACTION_MASK = 0xF 288 ACT_ACTION_MASK = 0xF
282 }; 289 };
283 290
284 // Internal representation of time. During collection, this is in "ticks" 291 // Internal representation of time. During collection, this is in "ticks"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 friend class ActivityUserData; 385 friend class ActivityUserData;
379 386
380 ValueType type_; 387 ValueType type_;
381 uint64_t short_value_; // Used to hold copy of numbers, etc. 388 uint64_t short_value_; // Used to hold copy of numbers, etc.
382 std::string long_value_; // Used to hold copy of raw/string data. 389 std::string long_value_; // Used to hold copy of raw/string data.
383 StringPiece ref_value_; // Used to hold reference to external data. 390 StringPiece ref_value_; // Used to hold reference to external data.
384 }; 391 };
385 392
386 using Snapshot = std::map<std::string, TypedValue>; 393 using Snapshot = std::map<std::string, TypedValue>;
387 394
395 ActivityUserData();
388 ActivityUserData(void* memory, size_t size); 396 ActivityUserData(void* memory, size_t size);
389 virtual ~ActivityUserData(); 397 virtual ~ActivityUserData();
390 398
391 // Gets the unique ID number for this user data. If this changes then the 399 // Gets the unique ID number for this user data. If this changes then the
392 // contents have been overwritten by another thread. The return value is 400 // contents have been overwritten by another thread. The return value is
393 // always non-zero unless it's actually just a data "sink". 401 // always non-zero unless it's actually just a data "sink".
394 uint32_t id() const { 402 uint32_t id() const {
395 return header_ ? header_->owner.data_id.load(std::memory_order_relaxed) : 0; 403 return header_ ? header_->owner.data_id.load(std::memory_order_relaxed) : 0;
396 } 404 }
397 405
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 int64_t process_id = 0; 580 int64_t process_id = 0;
573 int64_t thread_id = 0; 581 int64_t thread_id = 0;
574 582
575 // The current stack of activities that are underway for this thread. It 583 // The current stack of activities that are underway for this thread. It
576 // is limited in its maximum size with later entries being left off. 584 // is limited in its maximum size with later entries being left off.
577 std::vector<Activity> activity_stack; 585 std::vector<Activity> activity_stack;
578 586
579 // The current total depth of the activity stack, including those later 587 // The current total depth of the activity stack, including those later
580 // entries not recorded in the |activity_stack| vector. 588 // entries not recorded in the |activity_stack| vector.
581 uint32_t activity_stack_depth = 0; 589 uint32_t activity_stack_depth = 0;
590
591 // The last recorded "exception" activity.
592 Activity last_exception;
582 }; 593 };
583 594
584 // This is the base class for having the compiler manage an activity on the 595 // This is the base class for having the compiler manage an activity on the
585 // tracker's stack. It does nothing but call methods on the passed |tracker| 596 // tracker's stack. It does nothing but call methods on the passed |tracker|
586 // if it is not null, making it safe (and cheap) to create these objects 597 // if it is not null, making it safe (and cheap) to create these objects
587 // even if activity tracking is not enabled. 598 // even if activity tracking is not enabled.
588 class BASE_EXPORT ScopedActivity { 599 class BASE_EXPORT ScopedActivity {
589 public: 600 public:
590 ScopedActivity(ThreadActivityTracker* tracker, 601 ScopedActivity(ThreadActivityTracker* tracker,
591 const void* program_counter, 602 const void* program_counter,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 ActivityTrackerMemoryAllocator* allocator); 666 ActivityTrackerMemoryAllocator* allocator);
656 667
657 // Returns if there is true use-data associated with a given ActivityId since 668 // Returns if there is true use-data associated with a given ActivityId since
658 // it's possible than any returned object is just a sink. 669 // it's possible than any returned object is just a sink.
659 bool HasUserData(ActivityId id); 670 bool HasUserData(ActivityId id);
660 671
661 // Release the user-data information for an activity. 672 // Release the user-data information for an activity.
662 void ReleaseUserData(ActivityId id, 673 void ReleaseUserData(ActivityId id,
663 ActivityTrackerMemoryAllocator* allocator); 674 ActivityTrackerMemoryAllocator* allocator);
664 675
676 // Save an exception.
677 void ExceptionActivity(const void* program_counter,
manzagop (departed) 2017/03/20 14:29:55 nit: add a verb, eg [Store/Record/Save]ExceptionAc
bcwhite 2017/03/21 12:25:06 Done.
678 const void* origin,
679 Activity::Type type,
680 const ActivityData& data);
681
665 // Returns whether the current data is valid or not. It is not valid if 682 // Returns whether the current data is valid or not. It is not valid if
666 // corruption has been detected in the header or other data structures. 683 // corruption has been detected in the header or other data structures.
667 bool IsValid() const; 684 bool IsValid() const;
668 685
669 // Gets a copy of the tracker contents for analysis. Returns false if a 686 // Gets a copy of the tracker contents for analysis. Returns false if a
670 // snapshot was not possible, perhaps because the data is not valid; the 687 // snapshot was not possible, perhaps because the data is not valid; the
671 // contents of |output_snapshot| are undefined in that case. The current 688 // contents of |output_snapshot| are undefined in that case. The current
672 // implementation does not support concurrent snapshot operations. 689 // implementation does not support concurrent snapshot operations.
673 bool CreateSnapshot(Snapshot* output_snapshot) const; 690 bool CreateSnapshot(Snapshot* output_snapshot) const;
674 691
(...skipping 10 matching lines...) Expand all
685 ProcessId* out_id, 702 ProcessId* out_id,
686 int64_t* out_stamp); 703 int64_t* out_stamp);
687 704
688 // Calculates the memory size required for a given stack depth, including 705 // Calculates the memory size required for a given stack depth, including
689 // the internal header structure for the stack. 706 // the internal header structure for the stack.
690 static size_t SizeForStackDepth(int stack_depth); 707 static size_t SizeForStackDepth(int stack_depth);
691 708
692 private: 709 private:
693 friend class ActivityTrackerTest; 710 friend class ActivityTrackerTest;
694 711
712 std::unique_ptr<ActivityUserData> CreateUserDataForActivity(
713 Activity* activity,
714 ActivityTrackerMemoryAllocator* allocator);
715
695 Header* const header_; // Pointer to the Header structure. 716 Header* const header_; // Pointer to the Header structure.
696 Activity* const stack_; // The stack of activities. 717 Activity* const stack_; // The stack of activities.
697 const uint32_t stack_slots_; // The total number of stack slots. 718 const uint32_t stack_slots_; // The total number of stack slots.
698 719
699 bool valid_ = false; // Tracks whether the data is valid or not. 720 bool valid_ = false; // Tracks whether the data is valid or not.
700 721
701 base::ThreadChecker thread_checker_; 722 base::ThreadChecker thread_checker_;
702 723
703 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker); 724 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker);
704 }; 725 };
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 const FilePath::StringType& args) { 934 const FilePath::StringType& args) {
914 GlobalActivityTracker* tracker = Get(); 935 GlobalActivityTracker* tracker = Get();
915 if (tracker) 936 if (tracker)
916 tracker->RecordProcessLaunch(process_id, exe, args); 937 tracker->RecordProcessLaunch(process_id, exe, args);
917 } 938 }
918 static void RecordProcessExitIfEnabled(ProcessId process_id, int exit_code) { 939 static void RecordProcessExitIfEnabled(ProcessId process_id, int exit_code) {
919 GlobalActivityTracker* tracker = Get(); 940 GlobalActivityTracker* tracker = Get();
920 if (tracker) 941 if (tracker)
921 tracker->RecordProcessExit(process_id, exit_code); 942 tracker->RecordProcessExit(process_id, exit_code);
922 } 943 }
944
923 // Sets the "phase" of the current process, useful for knowing what it was 945 // Sets the "phase" of the current process, useful for knowing what it was
924 // doing when it last reported. 946 // doing when it last reported.
925 void SetProcessPhase(ProcessPhase phase); 947 void SetProcessPhase(ProcessPhase phase);
926 static void SetProcessPhaseIfEnabled(ProcessPhase phase) { 948 static void SetProcessPhaseIfEnabled(ProcessPhase phase) {
927 GlobalActivityTracker* tracker = Get(); 949 GlobalActivityTracker* tracker = Get();
928 if (tracker) 950 if (tracker)
929 tracker->SetProcessPhase(phase); 951 tracker->SetProcessPhase(phase);
930 } 952 }
931 953
932 // Records a log message. The current implementation does NOT recycle these 954 // Records a log message. The current implementation does NOT recycle these
(...skipping 18 matching lines...) Expand all
951 // this, construction of a GlobalActivityTracker will cause all existing 973 // this, construction of a GlobalActivityTracker will cause all existing
952 // active field trials to be fetched and recorded. 974 // active field trials to be fetched and recorded.
953 void RecordFieldTrial(const std::string& trial_name, StringPiece group_name); 975 void RecordFieldTrial(const std::string& trial_name, StringPiece group_name);
954 static void RecordFieldTrialIfEnabled(const std::string& trial_name, 976 static void RecordFieldTrialIfEnabled(const std::string& trial_name,
955 StringPiece group_name) { 977 StringPiece group_name) {
956 GlobalActivityTracker* tracker = Get(); 978 GlobalActivityTracker* tracker = Get();
957 if (tracker) 979 if (tracker)
958 tracker->RecordFieldTrial(trial_name, group_name); 980 tracker->RecordFieldTrial(trial_name, group_name);
959 } 981 }
960 982
983 // Record exception information for the current thread and return space where
manzagop (departed) 2017/03/20 14:29:55 No space is returned?
bcwhite 2017/03/21 12:25:06 Done.
984 // additional information may be recorded.
985 // TODO(bcwhite): More parameters (space for 4 + 64 bits).
986 ALWAYS_INLINE
987 void RecordException(const void* origin) {
988 return RecordExceptionImpl(::tracked_objects::GetProgramCounter(), origin);
989 }
990
961 // Accesses the process data record for storing arbitrary key/value pairs. 991 // Accesses the process data record for storing arbitrary key/value pairs.
962 // Updates to this are thread-safe. 992 // Updates to this are thread-safe.
963 ActivityUserData& process_data() { return process_data_; } 993 ActivityUserData& process_data() { return process_data_; }
964 994
965 // Accesses the global data record for storing arbitrary key/value pairs. 995 // Accesses the global data record for storing arbitrary key/value pairs.
966 // Updates to this are thread-safe. 996 // Updates to this are thread-safe.
967 ActivityUserData& global_data() { return global_data_; } 997 ActivityUserData& global_data() { return global_data_; }
968 998
969 private: 999 private:
970 friend class GlobalActivityAnalyzer; 1000 friend class GlobalActivityAnalyzer;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 // Creates a global tracker using a given persistent-memory |allocator| and 1098 // Creates a global tracker using a given persistent-memory |allocator| and
1069 // providing the given |stack_depth| to each thread tracker it manages. The 1099 // providing the given |stack_depth| to each thread tracker it manages. The
1070 // created object is activated so tracking has already started upon return. 1100 // created object is activated so tracking has already started upon return.
1071 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator, 1101 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator,
1072 int stack_depth); 1102 int stack_depth);
1073 1103
1074 // Returns the memory used by an activity-tracker managed by this class. 1104 // Returns the memory used by an activity-tracker managed by this class.
1075 // It is called during the destruction of a ManagedActivityTracker object. 1105 // It is called during the destruction of a ManagedActivityTracker object.
1076 void ReturnTrackerMemory(ManagedActivityTracker* tracker); 1106 void ReturnTrackerMemory(ManagedActivityTracker* tracker);
1077 1107
1108 // Records exception information.
1109 void RecordExceptionImpl(const void* pc, const void* origin);
1110
1078 // Releases the activity-tracker associcated with thread. It is called 1111 // Releases the activity-tracker associcated with thread. It is called
1079 // automatically when a thread is joined and thus there is nothing more to 1112 // automatically when a thread is joined and thus there is nothing more to
1080 // be tracked. |value| is a pointer to a ManagedActivityTracker. 1113 // be tracked. |value| is a pointer to a ManagedActivityTracker.
1081 static void OnTLSDestroy(void* value); 1114 static void OnTLSDestroy(void* value);
1082 1115
1083 // Does process-exit work. This can be run on any thread. 1116 // Does process-exit work. This can be run on any thread.
1084 void CleanupAfterProcess(ProcessId process_id, 1117 void CleanupAfterProcess(ProcessId process_id,
1085 int64_t exit_stamp, 1118 int64_t exit_stamp,
1086 int exit_code, 1119 int exit_code,
1087 std::string&& command_line); 1120 std::string&& command_line);
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 ScopedProcessWaitActivity(const void* program_counter, 1294 ScopedProcessWaitActivity(const void* program_counter,
1262 const base::Process* process); 1295 const base::Process* process);
1263 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); 1296 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity);
1264 }; 1297 };
1265 #endif 1298 #endif
1266 1299
1267 } // namespace debug 1300 } // namespace debug
1268 } // namespace base 1301 } // namespace base
1269 1302
1270 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ 1303 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_
OLDNEW
« no previous file with comments | « no previous file | base/debug/activity_tracker.cc » ('j') | base/debug/activity_tracker.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698