Closed
Bug 1050445
Opened 10 years ago
Closed 10 years ago
Add support for tracking callstacks to BlockingResourceBase
Categories
(Core :: XPCOM, defect)
Core
XPCOM
Tracking
()
RESOLVED
FIXED
mozilla34
People
(Reporter: erahm, Assigned: erahm)
References
Details
Attachments
(5 files)
3.44 KB,
patch
|
froydnj
:
review+
|
Details | Diff | Splinter Review |
2.48 KB,
patch
|
froydnj
:
review+
|
Details | Diff | Splinter Review |
5.90 KB,
patch
|
froydnj
:
review+
|
Details | Diff | Splinter Review |
3.89 KB,
patch
|
n.nethercote
:
review+
|
Details | Diff | Splinter Review |
4.04 KB,
patch
|
mccr8
:
review+
|
Details | Diff | Splinter Review |
This is a followup to bug 1049068 where we removed callstack handling from the DeadlockDetector.
Previously callstack tracking required a tracemalloc build. In this incarnation I'd like to track the callstacks in BlockingResourceBase itself, this will allow us to avoid grabbing the DeadlockDetector master lock for cases where this is the first lock a thread is acquiring.
The implementation would probably just use NS_StackWalk directly and store an array of addresses. When a deadlock is detected we can then use the AddressCache (or whatever it's called now) to convert the addresses to proper names, rather than performing the lookup at the time of locking like the previous implementation did.
Vaguely here's what I'm thinking:
BlockingResourceBase:
#ifdef MOZ_TRACK_CALLSTACKS
void* mCurrentStack[];
void* mFirstStack[];
#endif
BlockingResourceBase::Acquire:
GrabLock();
#ifdef MOZ_TRACK_CALLSTACKS
mCurrentStack = GetCallstack();
if (!mFirstStack)
mFirstStack = mCurrentStack;
#endif
BlockingResourceBase::Release:
#ifdef MOZ_TRACK_CALLSTACKS
Clear(mCurrentStack);
#endif
LetGoOfTheLock();
Assignee | ||
Comment 1•10 years ago
|
||
This prepares for having an alternate acquisition state definition.
Attachment #8471721 -
Flags: review?(nfroyd)
Assignee | ||
Updated•10 years ago
|
Assignee: nobody → erahm
Status: NEW → ASSIGNED
Assignee | ||
Comment 2•10 years ago
|
||
This adds a ClearAcquisitionState function that is used instead of setting the acquisition state to false directly.
Attachment #8471722 -
Flags: review?(nfroyd)
Assignee | ||
Comment 3•10 years ago
|
||
This patch introduces the option to capture callstacks and plugs in the alternate AcquisitionState definition as a nsAutoTArray<void*, 24>.
Attachment #8471725 -
Flags: review?(nfroyd)
Assignee | ||
Comment 4•10 years ago
|
||
Add stack snapshots for each acquisition context by using NS_StackWalk.
Attachment #8471729 -
Flags: review?(n.nethercote)
Assignee | ||
Comment 5•10 years ago
|
||
This adds stack printing in deadlock scenarious using CodeAddressService. The implementation is essentially lifted from nsTraceRefcnt.
Attachment #8471732 -
Flags: review?(continuation)
Updated•10 years ago
|
Attachment #8471721 -
Flags: review?(nfroyd) → review+
Updated•10 years ago
|
Attachment #8471722 -
Flags: review?(nfroyd) → review+
Comment 6•10 years ago
|
||
Comment on attachment 8471725 [details] [diff] [review]
Part 3: Add stack trace holders
Review of attachment 8471725 [details] [diff] [review]:
-----------------------------------------------------------------
::: xpcom/glue/BlockingResourceBase.cpp
@@ +43,5 @@
> +#ifdef MOZ_CALLSTACK_DISABLED
> + #define IS_ACQUIRED(callstack) (callstack)
> +#else
> + #define IS_ACQUIRED(callstack) (!callstack.IsEmpty())
> +#endif
I feel like this would be better as a private member function.
::: xpcom/glue/BlockingResourceBase.h
@@ +101,3 @@
> typedef bool AcquisitionState;
> +#else
> + typedef nsAutoTArray<void*, 24> AcquisitionState;
This is going to be quite some overhead for each and every BlockingResourceBase. I think I'd just make this nsTArray<void*> unless we find that the extra space really helps. (The previous version had heap-allocated stacks IIRC, so I don't think we need to change that here.)
Attachment #8471725 -
Flags: review?(nfroyd) → review+
Assignee | ||
Comment 7•10 years ago
|
||
Comment on attachment 8471725 [details] [diff] [review]
Part 3: Add stack trace holders
Review of attachment 8471725 [details] [diff] [review]:
-----------------------------------------------------------------
::: xpcom/glue/BlockingResourceBase.cpp
@@ +43,5 @@
> +#ifdef MOZ_CALLSTACK_DISABLED
> + #define IS_ACQUIRED(callstack) (callstack)
> +#else
> + #define IS_ACQUIRED(callstack) (!callstack.IsEmpty())
> +#endif
Good point, the fewer macros the better.
::: xpcom/glue/BlockingResourceBase.h
@@ +101,3 @@
> typedef bool AcquisitionState;
> +#else
> + typedef nsAutoTArray<void*, 24> AcquisitionState;
I'm somewhat following the DMD implementation which uses a fixed sized array and limits the stacks to 24 calls.
My thinking here is that this will only be enabled when someone hits a deadlock, at that point we don't really care about memory but we probably care about performance.
Performance implications:
nsAutoTArray - fixed size, no allocations, no deallocations as long as we stay within the size
nsTArray - allocates on first append, will double storage thereafter (so at 2, 4, 8, 16) involving allocation and copying of elements. Will deallocate storage when cleared, so each time we lock and unlock we'll go through the whole alloc/dealloc cycle again.
Memory implications:
From previous profiling I think I saw the number of live mutexes peak around 1000.
nsAutoTArray - this adds ~384 bytes per mutex (on 64-bit), so we're looking at a grand total of ~384K overhead
nsTArray - in best case scenario we say every lock is unlocked, so we're only keeping track of firstSeen. We'll also assume a 24 stack limit. That means ~1/2 of the nsAutoTArray overhead, or ~192K
Assignee | ||
Comment 8•10 years ago
|
||
(In reply to Eric Rahm [:erahm] from comment #7)
> nsTArray - in best case scenario we say every lock is unlocked, so we're
> only keeping track of firstSeen. We'll also assume a 24 stack limit. That
> means ~1/2 of the nsAutoTArray overhead, or ~192K
And since nsTArray will actually allocate 32 entries instead of 24 the overhead is more like ~256K.
Comment 9•10 years ago
|
||
(In reply to Eric Rahm [:erahm] from comment #7)
> Comment on attachment 8471725 [details] [diff] [review]
> Part 3: Add stack trace holders
>
> Review of attachment 8471725 [details] [diff] [review]:
> -----------------------------------------------------------------
>
> ::: xpcom/glue/BlockingResourceBase.cpp
> @@ +43,5 @@
> > +#ifdef MOZ_CALLSTACK_DISABLED
> > + #define IS_ACQUIRED(callstack) (callstack)
> > +#else
> > + #define IS_ACQUIRED(callstack) (!callstack.IsEmpty())
> > +#endif
>
> Good point, the fewer macros the better.
>
> ::: xpcom/glue/BlockingResourceBase.h
> @@ +101,3 @@
> > typedef bool AcquisitionState;
> > +#else
> > + typedef nsAutoTArray<void*, 24> AcquisitionState;
>
> I'm somewhat following the DMD implementation which uses a fixed sized array
> and limits the stacks to 24 calls.
>
> My thinking here is that this will only be enabled when someone hits a
> deadlock, at that point we don't really care about memory but we probably
> care about performance.
I guess if we have the stack tracing turned on, we're eventually going to allocate space for the arrays anyway at some point. Might as well allocate them upfront, then. nsAutoTArray wfm, then.
Comment 10•10 years ago
|
||
Comment on attachment 8471732 [details] [diff] [review]
Part 5: Print stacks
Review of attachment 8471732 [details] [diff] [review]:
-----------------------------------------------------------------
::: xpcom/glue/BlockingResourceBase.cpp
@@ +122,5 @@
> return maybeImminent;
> }
>
> +#ifndef MOZ_CALLSTACK_DISABLED
> +class CodeAddressServiceWriter MOZ_FINAL
It seems like you should factor all of this out of nsTraceRefCnt into a new header if it is really just the same code as exists already.
I assume this ends up producing a ton of stack traces? Also, I think Kyle told me the code address service is broken on B2G or something, so watch out for that...
Attachment #8471732 -
Flags: review?(continuation) → review+
Comment 11•10 years ago
|
||
Comment on attachment 8471729 [details] [diff] [review]
Part 4: Take stack snapshots
Review of attachment 8471729 [details] [diff] [review]:
-----------------------------------------------------------------
Seems ok, but I don't feel like I have much expertise for this patch.
Attachment #8471729 -
Flags: review?(n.nethercote) → review+
Assignee | ||
Comment 12•10 years ago
|
||
(In reply to Andrew McCreight [:mccr8] from comment #10)
> Comment on attachment 8471732 [details] [diff] [review]
> Part 5: Print stacks
>
> Review of attachment 8471732 [details] [diff] [review]:
> -----------------------------------------------------------------
>
> ::: xpcom/glue/BlockingResourceBase.cpp
> @@ +122,5 @@
> > return maybeImminent;
> > }
> >
> > +#ifndef MOZ_CALLSTACK_DISABLED
> > +class CodeAddressServiceWriter MOZ_FINAL
>
> It seems like you should factor all of this out of nsTraceRefCnt into a new
> header if it is really just the same code as exists already.
I'll file a followup for that, it seems like there could be further refactoring of CodeAddressService to make it easier to use.
Assignee | ||
Comment 13•10 years ago
|
||
tbpl is somewhat busted, but the try looks ok: https://tbpl.mozilla.org/?tree=Try&rev=b954908415ae
Assignee | ||
Comment 14•10 years ago
|
||
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/a6466f92f173
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/a4d41b55d558
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/fddd58eca98b
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/8940df19f856
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/0a1d26661162
Comment 15•10 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/a6466f92f173
https://hg.mozilla.org/mozilla-central/rev/a4d41b55d558
https://hg.mozilla.org/mozilla-central/rev/fddd58eca98b
https://hg.mozilla.org/mozilla-central/rev/8940df19f856
https://hg.mozilla.org/mozilla-central/rev/0a1d26661162
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla34
You need to log in
before you can comment on or make changes to this bug.
Description
•