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

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

Issue 2702413006: Enable storing last-dispatched exception per-thread. (Closed)
Patch Set: addressed review comments by manzagop 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') | no next file with comments »
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 // Initialize the object either as a "sink" that just accepts and discards
396 // data or an active one that writes to a given (zeroed) memory block.
397 ActivityUserData();
388 ActivityUserData(void* memory, size_t size); 398 ActivityUserData(void* memory, size_t size);
389 virtual ~ActivityUserData(); 399 virtual ~ActivityUserData();
390 400
391 // Gets the unique ID number for this user data. If this changes then the 401 // 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 402 // contents have been overwritten by another thread. The return value is
393 // always non-zero unless it's actually just a data "sink". 403 // always non-zero unless it's actually just a data "sink".
394 uint32_t id() const { 404 uint32_t id() const {
395 return header_ ? header_->owner.data_id.load(std::memory_order_relaxed) : 0; 405 return header_ ? header_->owner.data_id.load(std::memory_order_relaxed) : 0;
396 } 406 }
397 407
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 int64_t process_id = 0; 582 int64_t process_id = 0;
573 int64_t thread_id = 0; 583 int64_t thread_id = 0;
574 584
575 // The current stack of activities that are underway for this thread. It 585 // 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. 586 // is limited in its maximum size with later entries being left off.
577 std::vector<Activity> activity_stack; 587 std::vector<Activity> activity_stack;
578 588
579 // The current total depth of the activity stack, including those later 589 // The current total depth of the activity stack, including those later
580 // entries not recorded in the |activity_stack| vector. 590 // entries not recorded in the |activity_stack| vector.
581 uint32_t activity_stack_depth = 0; 591 uint32_t activity_stack_depth = 0;
592
593 // The last recorded "exception" activity.
594 Activity last_exception;
582 }; 595 };
583 596
584 // This is the base class for having the compiler manage an activity on the 597 // 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| 598 // 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 599 // if it is not null, making it safe (and cheap) to create these objects
587 // even if activity tracking is not enabled. 600 // even if activity tracking is not enabled.
588 class BASE_EXPORT ScopedActivity { 601 class BASE_EXPORT ScopedActivity {
589 public: 602 public:
590 ScopedActivity(ThreadActivityTracker* tracker, 603 ScopedActivity(ThreadActivityTracker* tracker,
591 const void* program_counter, 604 const void* program_counter,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 ActivityTrackerMemoryAllocator* allocator); 668 ActivityTrackerMemoryAllocator* allocator);
656 669
657 // Returns if there is true use-data associated with a given ActivityId since 670 // 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. 671 // it's possible than any returned object is just a sink.
659 bool HasUserData(ActivityId id); 672 bool HasUserData(ActivityId id);
660 673
661 // Release the user-data information for an activity. 674 // Release the user-data information for an activity.
662 void ReleaseUserData(ActivityId id, 675 void ReleaseUserData(ActivityId id,
663 ActivityTrackerMemoryAllocator* allocator); 676 ActivityTrackerMemoryAllocator* allocator);
664 677
678 // Save an exception.
679 void RecordExceptionActivity(const void* program_counter,
680 const void* origin,
681 Activity::Type type,
682 const ActivityData& data);
683
665 // Returns whether the current data is valid or not. It is not valid if 684 // 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. 685 // corruption has been detected in the header or other data structures.
667 bool IsValid() const; 686 bool IsValid() const;
668 687
669 // Gets a copy of the tracker contents for analysis. Returns false if a 688 // 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 689 // snapshot was not possible, perhaps because the data is not valid; the
671 // contents of |output_snapshot| are undefined in that case. The current 690 // contents of |output_snapshot| are undefined in that case. The current
672 // implementation does not support concurrent snapshot operations. 691 // implementation does not support concurrent snapshot operations.
673 bool CreateSnapshot(Snapshot* output_snapshot) const; 692 bool CreateSnapshot(Snapshot* output_snapshot) const;
674 693
(...skipping 10 matching lines...) Expand all
685 ProcessId* out_id, 704 ProcessId* out_id,
686 int64_t* out_stamp); 705 int64_t* out_stamp);
687 706
688 // Calculates the memory size required for a given stack depth, including 707 // Calculates the memory size required for a given stack depth, including
689 // the internal header structure for the stack. 708 // the internal header structure for the stack.
690 static size_t SizeForStackDepth(int stack_depth); 709 static size_t SizeForStackDepth(int stack_depth);
691 710
692 private: 711 private:
693 friend class ActivityTrackerTest; 712 friend class ActivityTrackerTest;
694 713
714 std::unique_ptr<ActivityUserData> CreateUserDataForActivity(
715 Activity* activity,
716 ActivityTrackerMemoryAllocator* allocator);
717
695 Header* const header_; // Pointer to the Header structure. 718 Header* const header_; // Pointer to the Header structure.
696 Activity* const stack_; // The stack of activities. 719 Activity* const stack_; // The stack of activities.
697 const uint32_t stack_slots_; // The total number of stack slots. 720 const uint32_t stack_slots_; // The total number of stack slots.
698 721
699 bool valid_ = false; // Tracks whether the data is valid or not. 722 bool valid_ = false; // Tracks whether the data is valid or not.
700 723
701 base::ThreadChecker thread_checker_; 724 base::ThreadChecker thread_checker_;
702 725
703 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker); 726 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker);
704 }; 727 };
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 const FilePath::StringType& args) { 936 const FilePath::StringType& args) {
914 GlobalActivityTracker* tracker = Get(); 937 GlobalActivityTracker* tracker = Get();
915 if (tracker) 938 if (tracker)
916 tracker->RecordProcessLaunch(process_id, exe, args); 939 tracker->RecordProcessLaunch(process_id, exe, args);
917 } 940 }
918 static void RecordProcessExitIfEnabled(ProcessId process_id, int exit_code) { 941 static void RecordProcessExitIfEnabled(ProcessId process_id, int exit_code) {
919 GlobalActivityTracker* tracker = Get(); 942 GlobalActivityTracker* tracker = Get();
920 if (tracker) 943 if (tracker)
921 tracker->RecordProcessExit(process_id, exit_code); 944 tracker->RecordProcessExit(process_id, exit_code);
922 } 945 }
946
923 // Sets the "phase" of the current process, useful for knowing what it was 947 // Sets the "phase" of the current process, useful for knowing what it was
924 // doing when it last reported. 948 // doing when it last reported.
925 void SetProcessPhase(ProcessPhase phase); 949 void SetProcessPhase(ProcessPhase phase);
926 static void SetProcessPhaseIfEnabled(ProcessPhase phase) { 950 static void SetProcessPhaseIfEnabled(ProcessPhase phase) {
927 GlobalActivityTracker* tracker = Get(); 951 GlobalActivityTracker* tracker = Get();
928 if (tracker) 952 if (tracker)
929 tracker->SetProcessPhase(phase); 953 tracker->SetProcessPhase(phase);
930 } 954 }
931 955
932 // Records a log message. The current implementation does NOT recycle these 956 // 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 975 // this, construction of a GlobalActivityTracker will cause all existing
952 // active field trials to be fetched and recorded. 976 // active field trials to be fetched and recorded.
953 void RecordFieldTrial(const std::string& trial_name, StringPiece group_name); 977 void RecordFieldTrial(const std::string& trial_name, StringPiece group_name);
954 static void RecordFieldTrialIfEnabled(const std::string& trial_name, 978 static void RecordFieldTrialIfEnabled(const std::string& trial_name,
955 StringPiece group_name) { 979 StringPiece group_name) {
956 GlobalActivityTracker* tracker = Get(); 980 GlobalActivityTracker* tracker = Get();
957 if (tracker) 981 if (tracker)
958 tracker->RecordFieldTrial(trial_name, group_name); 982 tracker->RecordFieldTrial(trial_name, group_name);
959 } 983 }
960 984
985 // Record exception information for the current thread.
986 // TODO(bcwhite): More parameters (space for 4 + 64 bits).
987 ALWAYS_INLINE
988 void RecordException(const void* origin) {
989 return RecordExceptionImpl(::tracked_objects::GetProgramCounter(), origin);
Sigurður Ásgeirsson 2017/03/21 14:15:06 Sorry, but I don't understand how this relates to
bcwhite 2017/03/21 14:40:40 I can add that.
Sigurður Ásgeirsson 2017/03/21 14:56:12 Cool.
bcwhite 2017/03/22 19:28:20 Done.
990 }
991
961 // Accesses the process data record for storing arbitrary key/value pairs. 992 // Accesses the process data record for storing arbitrary key/value pairs.
962 // Updates to this are thread-safe. 993 // Updates to this are thread-safe.
963 ActivityUserData& process_data() { return process_data_; } 994 ActivityUserData& process_data() { return process_data_; }
964 995
965 // Accesses the global data record for storing arbitrary key/value pairs. 996 // Accesses the global data record for storing arbitrary key/value pairs.
966 // Updates to this are thread-safe. 997 // Updates to this are thread-safe.
967 ActivityUserData& global_data() { return global_data_; } 998 ActivityUserData& global_data() { return global_data_; }
968 999
969 private: 1000 private:
970 friend class GlobalActivityAnalyzer; 1001 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 1099 // Creates a global tracker using a given persistent-memory |allocator| and
1069 // providing the given |stack_depth| to each thread tracker it manages. The 1100 // providing the given |stack_depth| to each thread tracker it manages. The
1070 // created object is activated so tracking has already started upon return. 1101 // created object is activated so tracking has already started upon return.
1071 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator, 1102 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator,
1072 int stack_depth); 1103 int stack_depth);
1073 1104
1074 // Returns the memory used by an activity-tracker managed by this class. 1105 // Returns the memory used by an activity-tracker managed by this class.
1075 // It is called during the destruction of a ManagedActivityTracker object. 1106 // It is called during the destruction of a ManagedActivityTracker object.
1076 void ReturnTrackerMemory(ManagedActivityTracker* tracker); 1107 void ReturnTrackerMemory(ManagedActivityTracker* tracker);
1077 1108
1109 // Records exception information.
1110 void RecordExceptionImpl(const void* pc, const void* origin);
1111
1078 // Releases the activity-tracker associcated with thread. It is called 1112 // Releases the activity-tracker associcated with thread. It is called
1079 // automatically when a thread is joined and thus there is nothing more to 1113 // automatically when a thread is joined and thus there is nothing more to
1080 // be tracked. |value| is a pointer to a ManagedActivityTracker. 1114 // be tracked. |value| is a pointer to a ManagedActivityTracker.
1081 static void OnTLSDestroy(void* value); 1115 static void OnTLSDestroy(void* value);
1082 1116
1083 // Does process-exit work. This can be run on any thread. 1117 // Does process-exit work. This can be run on any thread.
1084 void CleanupAfterProcess(ProcessId process_id, 1118 void CleanupAfterProcess(ProcessId process_id,
1085 int64_t exit_stamp, 1119 int64_t exit_stamp,
1086 int exit_code, 1120 int exit_code,
1087 std::string&& command_line); 1121 std::string&& command_line);
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 ScopedProcessWaitActivity(const void* program_counter, 1295 ScopedProcessWaitActivity(const void* program_counter,
1262 const base::Process* process); 1296 const base::Process* process);
1263 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); 1297 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity);
1264 }; 1298 };
1265 #endif 1299 #endif
1266 1300
1267 } // namespace debug 1301 } // namespace debug
1268 } // namespace base 1302 } // namespace base
1269 1303
1270 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ 1304 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_
OLDNEW
« no previous file with comments | « no previous file | base/debug/activity_tracker.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698