Open Bug 338362 Opened 19 years ago Updated 3 years ago

Detect live |this| pointer on the stack when deleting a XPCOM object

Categories

(Core :: XPCOM, enhancement)

x86
Linux
enhancement

Tracking

()

People

(Reporter: feng.qian.moz, Unassigned)

Details

Attachments

(3 files)

When deleting a XPCOM object, walk the stack and check if the first element on each stack frame is the same as the deleting pointer. Many kungFuDeathGrip(this) in the code base can be detected. It only works on Linux debug mode, and the output should be post-processed by tools/rb/fix-linux-stack.pl to get readable stack traces. It is optimized to skip scoped nsCOMPtr. It is fast and has low false positive rate.
Attached patch part ISplinter Review
Attachment #222422 - Flags: review?
nsLiveStackRefCheck.h should be put in xpcom/base
Attached file nsLiveStackRefCheck.h
should be put in xpcom/base
Attachment #222423 - Attachment description: nsLiveStackRefCheck.h → nsLiveStackRefCheck.cpp
Attachment #222422 - Flags: review? → review?(bzbarsky)
Attachment #222423 - Flags: review?(bzbarsky)
Attachment #222424 - Flags: review?(bzbarsky)
I'm not particularly qualified to review this, and more importantly I'm not an XPCOM peer. Please request review from an XPCOM peer.
Attachment #222422 - Flags: review?(bzbarsky) → review?(benjamin)
Attachment #222423 - Flags: review?(bzbarsky) → review?(benjamin)
Attachment #222424 - Flags: review?(bzbarsky) → review?(benjamin)
I'm not going to have time to review this until later next week.
some comments: 1. cvsdo add with cvs diff -uN would be good. 2. don't add trailing whitespace to files 3. the files you're adding are Unix only which means their file names are inappropriate. 4. plasticmillion has a serviced version of stack walking, and this code should use it. if that means someone should help him get it landed, then that's what should be done. 5. this is the nth fork i've seen of this walking code which is getting really really really annoying (see 4).
Bsmedberg asked me to review. Here are some notes: - House style issues: - use PRBool, PRUintn/PRIntn, PR_TRUE/PR_FALSE, etc. - Indent early returns. - Untabify. - Diff to nsStackFrameUnix.cpp appears to be dead code and/or whitespace diffs. - Likewise nsTraceRefcntImpl.h - Not sure what the purpose of changes to tools/Makefile.in and tools/registry/Makefile.in are for; look like dead code? - Remove commented-out code in the middle of nsLiveStackRefCheck::Release. - Use more informative names: ptr and fp should be dyingPtr and fpOfLastAddRefCaller (or something similarly useful) in nsLiveStackRefCheck::Release. - Name and explain magic constants (2, 2, 2 and 4) in stack-frame walker; I can imagine why you believe they are correct, but it's not stated anywhere. - If I understand your scanner correctly, you're only looking at the slot two words beneath the frame pointer, which on i386 ABI is either the last argument word or (if it's a __thiscall__ frame) the 'this' pointer of the callee. So it seems to me you're only going to notice when there's an existing call in progress to your target 'this', not when there locals or argument pointers containing your target 'this'. Am I correct? It's not clear. If I'm correct above, then your initial comment seems inaccurate: you don't *find* kungFuDeathGrip(this) instances; you find places where the code *needs* a kungFuDeathGrip(this). Correct? I'm uncertain what you're aiming to detect, exactly. Please clarify. - Optimization logic is obscure. It takes several reads to make it obvious what the purpose of storing mCallerFP is. Add a comment that explains the motivation and reasoning. Something like this: We are going to search for a 'this' pointer in frames underneath us. The frame immediately beneath us is _class::Release(); let's call the frame beneath _class::Release() "frame X". Note that we also saved the frame pointer underneath the most recent call to __class::AddRef(), stored it in mCallerFP, and passed it into nsLiveStackRefCheck::Release as the 'fp' parameter. Therefore if frame X is the same frame as fp, and we are at refcount zero, we are probably looking at a short-lived object: it was last AddRef'ed in the same frame (or rather, a frame with the same address) as the frame we're releasing it from. So we assume that it's actually the same frame, and that it's unlikely that anyone stored an escaping 'this' pointer into a stack variable underneath frame X, and abort our scan early. This should save us scanning for most short-lived objects. - Perhaps add some commentary to the file nsLiveStackRefCheck.cpp that notes, again, all the assumptions you're making about ABI (gnuc, i386, libdl, frame pointers present); casual reader such as myself may find it disconcerting to see ABI assumptions sprinkled through code. NS_CHECK_LIVE_REF_ON_STACK looks like a "feature request" macro, not a "this code is only defined on one particular platform" macro. Initial gut reaction to ::GetCallerFP is "this might work, on one very specific platform..." As per comment above, you may also wish to rename the guard NS_CHECK_STACK_FOR_CALL_IN_PROGRESS_TO_DYING_REF or such, since it doesn't seem to scan locals.
Comment on attachment 222422 [details] [diff] [review] part I Cancelling reviews, please clarify the points Graydon mentioned.
Attachment #222422 - Flags: review?(benjamin)
Attachment #222423 - Flags: review?(benjamin)
Attachment #222424 - Flags: review?(benjamin)
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: