|
|
DescriptionStart BindStateBase ref count from 1 instead of 0
The first atomic increments of ref counts are generally unneeded if the
ref count starts from 1 instead of 0, and we can detect an invalid AddRef
from 0 to 1 in that case.
Especially, the ref count in BindStateBase is incremented 300k times in
its constructor by the first page load from the browser boot, and also
it sometimes hits invalid state.
Note that 300k atomic increments are probably not so time consuming as
we can measure.
This CL adds `base::AdoptRef` to scoped_refptr for ref counted types whose
ref count start from 1, and converts BindStateBase to use it.
Review-Url: https://codereview.chromium.org/2723423002
Cr-Commit-Position: refs/heads/master@{#461372}
Committed: https://chromium.googlesource.com/chromium/src/+/65f39693c549f42146b26cd35b13fa6a94fa0744
Patch Set 1 #Patch Set 2 : . #Patch Set 3 : fix #Patch Set 4 : +comment. +DCHECK. #
Total comments: 2
Patch Set 5 : tag struct -> enum #Patch Set 6 : . #Patch Set 7 : fix #Patch Set 8 : +test #
Total comments: 7
Patch Set 9 : wip #Patch Set 10 : . #
Total comments: 2
Patch Set 11 : rm dead code. +test #
Total comments: 2
Patch Set 12 : +MAKE_REF_COUNT_START_FROM_ONE. +document #
Total comments: 2
Patch Set 13 : s/MAKE_REF_COUNT_START_FROM_ONE/REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE()/ #
Messages
Total messages: 74 (60 generated)
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Description was changed from ========== Start BindStateBase ref count from 1 instead of 0 BUG= ========== to ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor until first page load from the browser boot, and also it sometimes hits invalid state. This CL adds a scoped_refptr constructor that doesn't increment the ref count, and converts BindStateBase to use it. ==========
Description was changed from ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor until first page load from the browser boot, and also it sometimes hits invalid state. This CL adds a scoped_refptr constructor that doesn't increment the ref count, and converts BindStateBase to use it. ========== to ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor until first page load from the browser boot, and also it sometimes hits invalid state. Note that 300k atomic increments are probably not so time consuming as we can measure. This CL adds a scoped_refptr constructor that doesn't increment the ref count, and converts BindStateBase to use it. ==========
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: cast_shell_android on master.tryserver.chromium.android (JOB_FAILED, https://build.chromium.org/p/tryserver.chromium.android/builders/cast_shell_a...)
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
Description was changed from ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor until first page load from the browser boot, and also it sometimes hits invalid state. Note that 300k atomic increments are probably not so time consuming as we can measure. This CL adds a scoped_refptr constructor that doesn't increment the ref count, and converts BindStateBase to use it. ========== to ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor by the first page load from the browser boot, and also it sometimes hits invalid state. Note that 300k atomic increments are probably not so time consuming as we can measure. This CL adds a scoped_refptr constructor that doesn't increment the ref count, and converts BindStateBase to use it. ==========
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Description was changed from ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor by the first page load from the browser boot, and also it sometimes hits invalid state. Note that 300k atomic increments are probably not so time consuming as we can measure. This CL adds a scoped_refptr constructor that doesn't increment the ref count, and converts BindStateBase to use it. ========== to ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor by the first page load from the browser boot, and also it sometimes hits invalid state. Note that 300k atomic increments are probably not so time consuming as we can measure. This CL adds `AdoptRef` to scoped_refptr for ref counted types whose ref count start from 1, and converts BindStateBase to use it. ==========
Description was changed from ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor by the first page load from the browser boot, and also it sometimes hits invalid state. Note that 300k atomic increments are probably not so time consuming as we can measure. This CL adds `AdoptRef` to scoped_refptr for ref counted types whose ref count start from 1, and converts BindStateBase to use it. ========== to ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor by the first page load from the browser boot, and also it sometimes hits invalid state. Note that 300k atomic increments are probably not so time consuming as we can measure. This CL adds `base::AdoptRef` to scoped_refptr for ref counted types whose ref count start from 1, and converts BindStateBase to use it. ==========
tzik@chromium.org changed reviewers: + dcheng@chromium.org
PTAL
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
"also it sometimes hits invalid state." Can you explain what this means? In general, I'm a little nervous about changes like this, since it goes against how all the other refcounting types in Chromium work. Are you planning more uses of this (i.e. for the swap() work?) outside of callback? https://codereview.chromium.org/2723423002/diff/60001/base/memory/ref_counted.h File base/memory/ref_counted.h (right): https://codereview.chromium.org/2723423002/diff/60001/base/memory/ref_counted... base/memory/ref_counted.h:391: struct AdoptRefTag {}; FWIW, the usual trick I've seen in the past is to use an enum here: for example, see https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/webor...
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: win_chromium_x64_rel_ng on master.tryserver.chromium.win (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.win/builders/win_chromium_x64_...)
The CQ bit was checked by tzik@chromium.org
The CQ bit was unchecked by tzik@chromium.org
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
On 2017/03/06 22:09:19, dcheng wrote: > "also it sometimes hits invalid state." There are a number of crash report on the callback destruction such as: http://crash/?q=stable_signature%20LIKE%20%27base%3A%3Ainternal%3A%3ACallback... http://crash/?q=stable_signature%20LIKE%20%27base%3A%3Ainternal%3A%3ABindStat... There might be various reason each, but I think some of them are UAF of callback objects that we can detect it in AddRef() as a 0 to 1 increment. Then, I think we can get actionable stack trace on the crash dashboard. > > Can you explain what this means? > > In general, I'm a little nervous about changes like this, since it goes against > how all the other refcounting types in Chromium work. Are you planning more uses > of this (i.e. for the swap() work?) outside of callback? I currently don't have enough time to migrate all use of ref count to this. But I think it's better to use 1-start ref count broadly, so that we can trap more ref count related UAF in the wild. # This is not related to swap() work. That was just a drive by clean up.
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
https://codereview.chromium.org/2723423002/diff/60001/base/memory/ref_counted.h File base/memory/ref_counted.h (right): https://codereview.chromium.org/2723423002/diff/60001/base/memory/ref_counted... base/memory/ref_counted.h:391: struct AdoptRefTag {}; On 2017/03/06 22:09:18, dcheng wrote: > FWIW, the usual trick I've seen in the past is to use an enum here: for example, > see > https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/webor... Done.
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
Is it possible to scope this to Callback only? I'm a bit uncomfortable with exposing AdoptRef, since: - the default RefCounted implementation can't be used safely with it - yet it's available in the base namespace Also acceptable would be figuring out a way to get Blink's DCHECKs (which verify that the reference is adopted, etc, but that feels even more complicated...)
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: cast_shell_linux on master.tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/cast_shell_linu...)
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
On 2017/03/08 07:39:43, dcheng wrote: > Is it possible to scope this to Callback only? I'm a bit uncomfortable with > exposing AdoptRef, since: > - the default RefCounted implementation can't be used safely with it > - yet it's available in the base namespace > > Also acceptable would be figuring out a way to get Blink's DCHECKs (which verify > that the reference is adopted, etc, but that feels even more complicated...) How about make non-zero initial value generally available rather than limit to Callback as PS8? RefCounted in PS8 provides an optional initial value of the reference count, which can be used with AdoptRef.
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
Sorry for the review delay =( https://codereview.chromium.org/2723423002/diff/140001/base/memory/ref_counted.h File base/memory/ref_counted.h (right): https://codereview.chromium.org/2723423002/diff/140001/base/memory/ref_counte... base/memory/ref_counted.h:39: explicit RefCountedBase(size_t initial_ref_count = 0) I think I would prefer that we have a default ctor which starts at 0 and then a single-argument constructor which takes a special tag to tell the refcount to start at 1. (We DCHECK so this should be noticed fairly quickly, but I think it would be better if subclasses couldn't specify the refcount directly) https://codereview.chromium.org/2723423002/diff/140001/base/memory/ref_counte... base/memory/ref_counted.h:84: return ref_count_ == 0; What is the purpose / necessity for these changes? https://codereview.chromium.org/2723423002/diff/140001/base/memory/ref_counte... base/memory/ref_counted.h:265: DCHECK(!t || t->HasOneRef()); Hmm... why would we want to handle a null |t| here? In general, it seems like we want this to always succeed. https://codereview.chromium.org/2723423002/diff/140001/base/memory/ref_counte... base/memory/ref_counted.h:278: return scoped_refptr<T>(obj); Not sure if it's possible, but it would be nice if we didn't have to do runtime selection. Is it possible to be clever here? For example, maybe we could do something like what C++03 move support used to do: it provided a macro that movable things would include in their class declaration, and we would use the presence of a typedef on T to determine if it should be treated as move-only or not. Perhaps we could do that here? Not sure if we could make the constructors work with that too... but if that's possible, that might be a nice safety improvement.
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
https://codereview.chromium.org/2723423002/diff/140001/base/memory/ref_counted.h File base/memory/ref_counted.h (right): https://codereview.chromium.org/2723423002/diff/140001/base/memory/ref_counte... base/memory/ref_counted.h:84: return ref_count_ == 0; On 2017/03/30 04:26:15, dcheng wrote: > What is the purpose / necessity for these changes? Oops, this is a contamination from another CL: http://crrev.com/2666423002. Reverted from this CL. https://codereview.chromium.org/2723423002/diff/140001/base/memory/ref_counte... base/memory/ref_counted.h:265: DCHECK(!t || t->HasOneRef()); On 2017/03/30 04:26:16, dcheng wrote: > Hmm... why would we want to handle a null |t| here? In general, it seems like we > want this to always succeed. OK, updated to force nun-null. https://codereview.chromium.org/2723423002/diff/140001/base/memory/ref_counte... base/memory/ref_counted.h:278: return scoped_refptr<T>(obj); On 2017/03/30 04:26:16, dcheng wrote: > Not sure if it's possible, but it would be nice if we didn't have to do runtime > selection. Is it possible to be clever here? > > For example, maybe we could do something like what C++03 move support used to > do: it provided a macro that movable things would include in their class > declaration, and we would use the presence of a typedef on T to determine if it > should be treated as move-only or not. Perhaps we could do that here? Not sure > if we could make the constructors work with that too... but if that's possible, > that might be a nice safety improvement. Trying that. https://codereview.chromium.org/2723423002/diff/180001/base/memory/ref_counte... File base/memory/ref_counted_unittest.cc (right): https://codereview.chromium.org/2723423002/diff/180001/base/memory/ref_counte... base/memory/ref_counted_unittest.cc:129: base::subtle::kStartRefCountFromOneTag; We should probably replace this with a macro.
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
LGTM https://codereview.chromium.org/2723423002/diff/180001/base/memory/ref_counte... File base/memory/ref_counted_unittest.cc (right): https://codereview.chromium.org/2723423002/diff/180001/base/memory/ref_counte... base/memory/ref_counted_unittest.cc:129: base::subtle::kStartRefCountFromOneTag; On 2017/03/30 13:16:28, tzik wrote: > We should probably replace this with a macro. Sounds good to me. (To give some background context: I think my original thought was we could use the absence of the tag to use the original start-from-zero behavior. In theory, this would let us incrementally migrate the codebase to using adoption semantics. But this way should be fine too: if a subclass declares a preference, it should still work.) https://codereview.chromium.org/2723423002/diff/200001/base/callback_internal.cc File base/callback_internal.cc (right): https://codereview.chromium.org/2723423002/diff/200001/base/callback_internal... base/callback_internal.cc:78: : bind_state_(bind_state ? AdoptRef(bind_state) : nullptr) { Can you remind me when we would bind a null state here? Codesearch doesn't work for this.
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Added document and a macro to opt-in. Could you take another look to them? https://codereview.chromium.org/2723423002/diff/200001/base/callback_internal.cc File base/callback_internal.cc (right): https://codereview.chromium.org/2723423002/diff/200001/base/callback_internal... base/callback_internal.cc:78: : bind_state_(bind_state ? AdoptRef(bind_state) : nullptr) { On 2017/03/30 21:15:25, dcheng wrote: > Can you remind me when we would bind a null state here? Codesearch doesn't work > for this. It's null when it's called from the default constructor of Callback. https://cs.chromium.org/chromium/src/base/callback.h?q=callback.h&dr=CSs&l=47
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
LGTM https://codereview.chromium.org/2723423002/diff/220001/base/memory/ref_counted.h File base/memory/ref_counted.h (right): https://codereview.chromium.org/2723423002/diff/220001/base/memory/ref_counte... base/memory/ref_counted.h:186: #define MAKE_REF_COUNT_START_FROM_ONE \ Two nits 1) Make this a function-style macro, so that a typo fails to compile. 2) Maybe name it something like START_REFCOUNT_AT_ONE() or REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE().
The CQ bit was checked by tzik@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
https://codereview.chromium.org/2723423002/diff/220001/base/memory/ref_counted.h File base/memory/ref_counted.h (right): https://codereview.chromium.org/2723423002/diff/220001/base/memory/ref_counte... base/memory/ref_counted.h:186: #define MAKE_REF_COUNT_START_FROM_ONE \ On 2017/04/03 00:07:28, dcheng wrote: > Two nits > 1) Make this a function-style macro, so that a typo fails to compile. > 2) Maybe name it something like START_REFCOUNT_AT_ONE() or > REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(). Done. Updated its name to REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE.
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
The CQ bit was checked by tzik@chromium.org
The patchset sent to the CQ was uploaded after l-g-t-m from dcheng@chromium.org Link to the patchset: https://codereview.chromium.org/2723423002/#ps240001 (title: "s/MAKE_REF_COUNT_START_FROM_ONE/REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE()/")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
CQ is committing da patch. Bot data: {"patchset_id": 240001, "attempt_start_ts": 1491196966573940, "parent_rev": "f98f8cb0517d4b28943102a007528063252e0ce0", "commit_rev": "65f39693c549f42146b26cd35b13fa6a94fa0744"}
Message was sent while issue was closed.
Description was changed from ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor by the first page load from the browser boot, and also it sometimes hits invalid state. Note that 300k atomic increments are probably not so time consuming as we can measure. This CL adds `base::AdoptRef` to scoped_refptr for ref counted types whose ref count start from 1, and converts BindStateBase to use it. ========== to ========== Start BindStateBase ref count from 1 instead of 0 The first atomic increments of ref counts are generally unneeded if the ref count starts from 1 instead of 0, and we can detect an invalid AddRef from 0 to 1 in that case. Especially, the ref count in BindStateBase is incremented 300k times in its constructor by the first page load from the browser boot, and also it sometimes hits invalid state. Note that 300k atomic increments are probably not so time consuming as we can measure. This CL adds `base::AdoptRef` to scoped_refptr for ref counted types whose ref count start from 1, and converts BindStateBase to use it. Review-Url: https://codereview.chromium.org/2723423002 Cr-Commit-Position: refs/heads/master@{#461372} Committed: https://chromium.googlesource.com/chromium/src/+/65f39693c549f42146b26cd35b13... ==========
Message was sent while issue was closed.
Committed patchset #13 (id:240001) as https://chromium.googlesource.com/chromium/src/+/65f39693c549f42146b26cd35b13... |