Index: base/debug/activity_tracker.h |
diff --git a/base/debug/activity_tracker.h b/base/debug/activity_tracker.h |
index fcf28b5c07d782d80168677912c762f7d71c26e3..3ba1e1c8b3d665a6f29f12ac82d945c8f5439ab5 100644 |
--- a/base/debug/activity_tracker.h |
+++ b/base/debug/activity_tracker.h |
@@ -96,6 +96,10 @@ struct OwningProcess { |
// sized types to ensure no interoperability problems between 32-bit and |
// 64-bit systems. |
union ActivityData { |
+ // Expected size for 32/64-bit check. |
+ // TODO(bcwhite): VC2015 doesn't allow statics in unions. Fix when it does. |
+ // static constexpr size_t kExpectedInstanceSize = 8; |
+ |
// Generic activities don't have any defined structure. |
struct { |
uint32_t id; // An arbitrary identifier used for association. |
@@ -233,6 +237,11 @@ class BASE_EXPORT ActivityTrackerMemoryAllocator { |
// the |data| field. All fields must be explicitly sized types to ensure no |
// interoperability problems between 32-bit and 64-bit systems. |
struct Activity { |
+ // Expected size for 32/64-bit check. |
+ static constexpr size_t kExpectedInstanceSize = |
+ 40 + 8 * kActivityCallStackSize + |
+ /*ActivityData::kExpectedInstanceSize=*/8; |
+ |
// The type of an activity on the stack. Activities are broken into |
// categories with the category ID taking the top 4 bits and the lower |
// bits representing an action within that category. This combination |
@@ -266,6 +275,9 @@ struct Activity { |
ACT_PROCESS_START = ACT_PROCESS, |
ACT_PROCESS_WAIT, |
+ // Exception activities indicate the occurence of something unexpected. |
+ ACT_EXCEPTION = 14 << 4, |
+ |
// Generic activities are user defined and can be anything. |
ACT_GENERIC = 15 << 4, |
@@ -377,6 +389,7 @@ class BASE_EXPORT ActivityUserData { |
using Snapshot = std::map<std::string, TypedValue>; |
+ ActivityUserData(); |
ActivityUserData(void* memory, size_t size); |
virtual ~ActivityUserData(); |
@@ -571,6 +584,9 @@ class BASE_EXPORT ThreadActivityTracker { |
// The current total depth of the activity stack, including those later |
// entries not recorded in the |activity_stack| vector. |
uint32_t activity_stack_depth = 0; |
+ |
+ // The last recorded "exception" activity. |
+ Activity last_exception; |
}; |
// This is the base class for having the compiler manage an activity on the |
@@ -654,6 +670,14 @@ class BASE_EXPORT ThreadActivityTracker { |
void ReleaseUserData(ActivityId id, |
ActivityTrackerMemoryAllocator* allocator); |
+ // Save an exception and return space for additional information. |
+ ActivityUserData& ExceptionActivity( |
+ const void* program_counter, |
+ const void* origin, |
+ Activity::Type type, |
+ const ActivityData& data, |
+ ActivityTrackerMemoryAllocator* allocator); |
+ |
// Returns whether the current data is valid or not. It is not valid if |
// corruption has been detected in the header or other data structures. |
bool IsValid() const; |
@@ -684,12 +708,19 @@ class BASE_EXPORT ThreadActivityTracker { |
private: |
friend class ActivityTrackerTest; |
+ std::unique_ptr<ActivityUserData> CreateUserDataForActivity( |
+ Activity* activity, |
+ ActivityTrackerMemoryAllocator* allocator); |
+ |
Header* const header_; // Pointer to the Header structure. |
Activity* const stack_; // The stack of activities. |
const uint32_t stack_slots_; // The total number of stack slots. |
bool valid_ = false; // Tracks whether the data is valid or not. |
+ // A user-data object for information associated with the last exception. |
+ std::unique_ptr<ActivityUserData> exception_data; |
+ |
base::ThreadChecker thread_checker_; |
DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker); |
@@ -729,6 +760,7 @@ class BASE_EXPORT GlobalActivityTracker { |
PROCESS_LAUNCH_FAILED = 2, |
PROCESS_EXITED_CLEANLY = 10, |
PROCESS_EXITED_WITH_CODE = 11, |
+ PROCESS_UNHANDLED_EXCEPTION = 50, |
manzagop (departed)
2017/02/24 19:06:14
Perhaps this should be kept separate (e.g. a hit-e
bcwhite
2017/02/24 19:10:58
Actually, I need to remove it because it writes to
|
// Add here whatever is useful for analysis. |
PROCESS_SHUTDOWN_STARTED = 100, |
@@ -907,6 +939,7 @@ class BASE_EXPORT GlobalActivityTracker { |
if (tracker) |
tracker->RecordProcessExit(process_id, exit_code); |
} |
+ |
// Sets the "phase" of the current process, useful for knowing what it was |
// doing when it last reported. |
void SetProcessPhase(ProcessPhase phase); |
@@ -929,6 +962,14 @@ class BASE_EXPORT GlobalActivityTracker { |
// active field trials to be fetched and recorded. |
void RecordFieldTrial(const std::string& trial_name, StringPiece group_name); |
+ // Record exception information for the current thread and return space where |
+ // additional information may be recorded. |
+ // TODO(bcwhite): More parameters (space for 4 + 64 bits). |
+ ALWAYS_INLINE |
+ ActivityUserData& RecordException(const void* origin) { |
+ return RecordExceptionImpl(::tracked_objects::GetProgramCounter(), origin); |
Sigurður Ásgeirsson
2017/02/24 18:37:41
no - this the program counter will have to come fr
bcwhite
2017/02/24 19:10:58
Every activity holds the PC of where it was create
|
+ } |
+ |
// Accesses the process data record for storing arbitrary key/value pairs. |
// Updates to this are thread-safe. |
ActivityUserData& process_data() { return process_data_; } |
@@ -1046,6 +1087,9 @@ class BASE_EXPORT GlobalActivityTracker { |
// It is called during the destruction of a ManagedActivityTracker object. |
void ReturnTrackerMemory(ManagedActivityTracker* tracker); |
+ // Records exception information. |
+ ActivityUserData& RecordExceptionImpl(const void* pc, const void* origin); |
+ |
// Releases the activity-tracker associcated with thread. It is called |
// automatically when a thread is joined and thus there is nothing more to |
// be tracked. |value| is a pointer to a ManagedActivityTracker. |