Blink already has WTF::bind. If we wanted to use base::Bind() in Blink, we should probably remove WTF::bind. At minimum, I think this should also involve:- Merging base::WeakPtr and WTF::WeakPtr- Figuring out scoped_ptr vs WTF::OwnPtr usage in Blink (I don't think we should use both of them)- Figuring out the thread-safety story (someone else can probably comment more on this, but I recall there were some issues with binding WTF::Strings on cross-thread tasks)base::Bind also has some features that WTF::bind does not:- It tries to enforce lifetime semantics of |this| when binding a method.- Binding a refcounted argument (that's not |this|) as a raw pointer is a compile-time error
Also, this is somewhat offtopic, but I looked at the Mojo in Blink patch, and it seems strange to me that //content depends on //third_party/WebKit but then parts of WebKit depend on //content. That doesn't seem like something we should do.
+1, I think allowing base::Bind at the boundary (platform/) makes sense if it simplifies our interaction with content. It also makes sense in WTF where we might wrap it or leverage it to implement something else. I don't think we should bring it to the rest of the codebase just yet.
I don't think we want scoped_refptr at this time.
- E
+1, I think allowing base::Bind at the boundary (platform/) makes sense if it simplifies our interaction with content. It also makes sense in WTF where we might wrap it or leverage it to implement something else. I don't think we should bring it to the rest of the codebase just yet.
I don't think we want scoped_refptr at this time.
- E
On Sep 29, 2015 11:55 AM, "Jeremy Roman" <jbr...@chromium.org> wrote:In the interest of caution, my preference would be to permit base::Bind in Blink only where it's needed by platform code interacting with Chromium code that accepts base::Callback arguments (i.e. places where today we'd create a Web* callback interface), and possibly in WTF where we could use it to adapt a base/ implementation onto a WTF interface to avoid code duplication.This lets us begin disentangling the dependencies without immediately trying to rewrite all of Blink (especially core/) with Chromium idioms. From there we can look at adding deeper dependencies, if we think that's worthwhile.On Tue, Sep 29, 2015 at 2:42 PM, Daniel Cheng <dch...@chromium.org> wrote:Blink already has WTF::bind. If we wanted to use base::Bind() in Blink, we should probably remove WTF::bind. At minimum, I think this should also involve:- Merging base::WeakPtr and WTF::WeakPtr- Figuring out scoped_ptr vs WTF::OwnPtr usage in Blink (I don't think we should use both of them)- Figuring out the thread-safety story (someone else can probably comment more on this, but I recall there were some issues with binding WTF::Strings on cross-thread tasks)
base::Bind also has some features that WTF::bind does not:- It tries to enforce lifetime semantics of |this| when binding a method.- Binding a refcounted argument (that's not |this|) as a raw pointer is a compile-time error
I and hiroshige@ have been thinking about making any potentially racy Blink classes identifiable via clang-plugin to make cross-thread post tasking safer in blink (rough design doc), if we start to bind more Blink classes with base::Bind or in cross-thread environment we might want to revisit this.
If we start to allow base::Bind in Blink code could we also add some restrictions like:
- Binding WTF::String to base::Bind should lead to a compile-time error
for the time being?
This disallows binding WTF::String even for same-thread post tasking, and wouldn't protect us from more subtle cases (e.g. KURL contains WTF::String, which means binding KURL for cross-thread post tasking is unsafe), but could save some easy crashy cases. (We, i.e. worker team and hiroshige@, have been fixing a lot of such crashes caused by binding WebString for cross-thread post tasking at Blink/Chromium boundary)
On Wed, Sep 30, 2015 at 4:12 AM, 'Elliott Sprehn' via blink-dev <blin...@chromium.org> wrote:+1, I think allowing base::Bind at the boundary (platform/) makes sense if it simplifies our interaction with content. It also makes sense in WTF where we might wrap it or leverage it to implement something else. I don't think we should bring it to the rest of the codebase just yet.
I don't think we want scoped_refptr at this time.
- E
On Sep 29, 2015 11:55 AM, "Jeremy Roman" <jbr...@chromium.org> wrote:In the interest of caution, my preference would be to permit base::Bind in Blink only where it's needed by platform code interacting with Chromium code that accepts base::Callback arguments (i.e. places where today we'd create a Web* callback interface), and possibly in WTF where we could use it to adapt a base/ implementation onto a WTF interface to avoid code duplication.This lets us begin disentangling the dependencies without immediately trying to rewrite all of Blink (especially core/) with Chromium idioms. From there we can look at adding deeper dependencies, if we think that's worthwhile.On Tue, Sep 29, 2015 at 2:42 PM, Daniel Cheng <dch...@chromium.org> wrote:Blink already has WTF::bind. If we wanted to use base::Bind() in Blink, we should probably remove WTF::bind. At minimum, I think this should also involve:- Merging base::WeakPtr and WTF::WeakPtr- Figuring out scoped_ptr vs WTF::OwnPtr usage in Blink (I don't think we should use both of them)- Figuring out the thread-safety story (someone else can probably comment more on this, but I recall there were some issues with binding WTF::Strings on cross-thread tasks)A few more differences from thread-safety pov:- WTF::bind deliberately returns OwnPtr while base::Bind returns copyable callback type- (Partly due to the above fact) base::Bind can never work safely with WTF::String in cross-thread post tasking
The problems with WTF::String stem from the fact that it is internally refcounted, but the refcounting is not thread-safe. https://docs.google.com/document/d/17qforp6RQ6GIy3Jr5qA04krKTyfZe3LdPQVTjYHyFpA/edit has the details (sorry, I think this is google.com only).
On Mon, Oct 12, 2015 at 4:42 PM, Daniel Cheng <dch...@chromium.org> wrote:The problems with WTF::String stem from the fact that it is internally refcounted, but the refcounting is not thread-safe. https://docs.google.com/document/d/17qforp6RQ6GIy3Jr5qA04krKTyfZe3LdPQVTjYHyFpA/edit has the details (sorry, I think this is google.com only).Oh :( This is a huge problem in chromium too FWIW. Any time you stick a RefCountedThreadSafe object into a Closure and PostTask it, you have no idea where it will be deleted. Often people want to do some thread-specific thing in the destructor and they just.. can't. So the (unfortunately) common pattern is to PostTask to the right thread from the destructor, but by then it's too late to handle the case that PostTask can fail.. so you can just leak/fail to destruct.
Hypothetically.. would making Callback move-only solve all of the problems here? I'm not sure how intractable that would be but it could help a lot in Chrome probably.
There's some mention of WTF callbacks being one-shot which differs from Base. But what impact does this have on WTF::String? We could perhaps provide a wrapper around a base::Callback like WTF::OneShotCallback that crashes if you try call it twice or something (we have a similar thing in cc::SingleReleaseCallback), or more specific wrappers in the places in blink that really care about this?
On Tue, Oct 13, 2015 at 8:52 AM, Dana Jansens <dan...@chromium.org> wrote:On Mon, Oct 12, 2015 at 4:42 PM, Daniel Cheng <dch...@chromium.org> wrote:The problems with WTF::String stem from the fact that it is internally refcounted, but the refcounting is not thread-safe. https://docs.google.com/document/d/17qforp6RQ6GIy3Jr5qA04krKTyfZe3LdPQVTjYHyFpA/edit has the details (sorry, I think this is google.com only).Oh :( This is a huge problem in chromium too FWIW. Any time you stick a RefCountedThreadSafe object into a Closure and PostTask it, you have no idea where it will be deleted. Often people want to do some thread-specific thing in the destructor and they just.. can't. So the (unfortunately) common pattern is to PostTask to the right thread from the destructor, but by then it's too late to handle the case that PostTask can fail.. so you can just leak/fail to destruct.WTF::String is NOT thread-safe ref-counted, yet it's used in cross-thread post tasking (partly because we have no other thread-safe string representation in Blink other than std::string), so the situation is probably worse.Hypothetically.. would making Callback move-only solve all of the problems here? I'm not sure how intractable that would be but it could help a lot in Chrome probably.There's some mention of WTF callbacks being one-shot which differs from Base. But what impact does this have on WTF::String? We could perhaps provide a wrapper around a base::Callback like WTF::OneShotCallback that crashes if you try call it twice or something (we have a similar thing in cc::SingleReleaseCallback), or more specific wrappers in the places in blink that really care about this?This is all very subtle but let me try to explain. (hiroshige@ could probably give more details and concrete examples)Having a move-only closure helps to avoid leaking a reference on the calling thread after postTask(). Or having a move-only wrapper for WTF::String (and all such racy classes) could be also useful. But this only solves one aspect, in order to safely pass a WTF::String to another thread one also needs to create an isolated copy of WTF::String which doesn't share any ref-counting with existing String objects. (I think this answers to one of your questions)And one more thing to note, the same thing needs to apply to all objects that contain WTF::String in any of their members. So if one wants to bind KURL for running a method on another thread, we first need to create an isolated copy of KURL without leaking any reference after postTask because KURL contains WTF::String. Ditto if one wants to bind an object that contains KURL.So the biggest problem is, even if we have move-only callback, the caller needs to choose the right one and does the right thing, and it's almost impractical to assume that everyone understands all these well and does the right thing (TM).So what hiroshige@ did in Blink was to make WTF::bind() always return move-only (so that no one can leave an unexpected reference after postTask), and to introduce a new WTF::bind() for cross-thread version which does this all (so that all cross-thread post tasking could be automatically taken care of, while keeping the same-thread post tasking to work as is with full benefit of ref-counting for performance).So getting back to the original question: if we could make Callback move-only in Chrome, yes I think it'd be helpful, but it doesn't solve all issues. If we could also make cross-thread(able) post tasking and same-thread post tasking distinguishable in Chrome, (say, by having ThreadSafeCallback and start asserting non-thread-safe callback usage on multi-threaded code) we could start to be comfortable allowing base::Bind in Blink, or allowing WTF::String used in other Chrome code.Sorry for lengthy response. Maybe we could have a quick VC to chat about this too?
On Mon, Oct 12, 2015 at 7:18 PM, Kinuko Yasuda <kin...@chromium.org> wrote:On Tue, Oct 13, 2015 at 8:52 AM, Dana Jansens <dan...@chromium.org> wrote:On Mon, Oct 12, 2015 at 4:42 PM, Daniel Cheng <dch...@chromium.org> wrote:The problems with WTF::String stem from the fact that it is internally refcounted, but the refcounting is not thread-safe. https://docs.google.com/document/d/17qforp6RQ6GIy3Jr5qA04krKTyfZe3LdPQVTjYHyFpA/edit has the details (sorry, I think this is google.com only).Oh :( This is a huge problem in chromium too FWIW. Any time you stick a RefCountedThreadSafe object into a Closure and PostTask it, you have no idea where it will be deleted. Often people want to do some thread-specific thing in the destructor and they just.. can't. So the (unfortunately) common pattern is to PostTask to the right thread from the destructor, but by then it's too late to handle the case that PostTask can fail.. so you can just leak/fail to destruct.WTF::String is NOT thread-safe ref-counted, yet it's used in cross-thread post tasking (partly because we have no other thread-safe string representation in Blink other than std::string), so the situation is probably worse.Hypothetically.. would making Callback move-only solve all of the problems here? I'm not sure how intractable that would be but it could help a lot in Chrome probably.There's some mention of WTF callbacks being one-shot which differs from Base. But what impact does this have on WTF::String? We could perhaps provide a wrapper around a base::Callback like WTF::OneShotCallback that crashes if you try call it twice or something (we have a similar thing in cc::SingleReleaseCallback), or more specific wrappers in the places in blink that really care about this?This is all very subtle but let me try to explain. (hiroshige@ could probably give more details and concrete examples)Having a move-only closure helps to avoid leaking a reference on the calling thread after postTask(). Or having a move-only wrapper for WTF::String (and all such racy classes) could be also useful. But this only solves one aspect, in order to safely pass a WTF::String to another thread one also needs to create an isolated copy of WTF::String which doesn't share any ref-counting with existing String objects. (I think this answers to one of your questions)And one more thing to note, the same thing needs to apply to all objects that contain WTF::String in any of their members. So if one wants to bind KURL for running a method on another thread, we first need to create an isolated copy of KURL without leaking any reference after postTask because KURL contains WTF::String. Ditto if one wants to bind an object that contains KURL.So the biggest problem is, even if we have move-only callback, the caller needs to choose the right one and does the right thing, and it's almost impractical to assume that everyone understands all these well and does the right thing (TM).So what hiroshige@ did in Blink was to make WTF::bind() always return move-only (so that no one can leave an unexpected reference after postTask), and to introduce a new WTF::bind() for cross-thread version which does this all (so that all cross-thread post tasking could be automatically taken care of, while keeping the same-thread post tasking to work as is with full benefit of ref-counting for performance).
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
On Thu, Oct 15, 2015 at 1:18 PM, Dana Jansens <dan...@chromium.org> wrote:On Mon, Oct 12, 2015 at 7:18 PM, Kinuko Yasuda <kin...@chromium.org> wrote:On Tue, Oct 13, 2015 at 8:52 AM, Dana Jansens <dan...@chromium.org> wrote:On Mon, Oct 12, 2015 at 4:42 PM, Daniel Cheng <dch...@chromium.org> wrote:The problems with WTF::String stem from the fact that it is internally refcounted, but the refcounting is not thread-safe. https://docs.google.com/document/d/17qforp6RQ6GIy3Jr5qA04krKTyfZe3LdPQVTjYHyFpA/edit has the details (sorry, I think this is google.com only).Oh :( This is a huge problem in chromium too FWIW. Any time you stick a RefCountedThreadSafe object into a Closure and PostTask it, you have no idea where it will be deleted. Often people want to do some thread-specific thing in the destructor and they just.. can't. So the (unfortunately) common pattern is to PostTask to the right thread from the destructor, but by then it's too late to handle the case that PostTask can fail.. so you can just leak/fail to destruct.WTF::String is NOT thread-safe ref-counted, yet it's used in cross-thread post tasking (partly because we have no other thread-safe string representation in Blink other than std::string), so the situation is probably worse.Hypothetically.. would making Callback move-only solve all of the problems here? I'm not sure how intractable that would be but it could help a lot in Chrome probably.There's some mention of WTF callbacks being one-shot which differs from Base. But what impact does this have on WTF::String? We could perhaps provide a wrapper around a base::Callback like WTF::OneShotCallback that crashes if you try call it twice or something (we have a similar thing in cc::SingleReleaseCallback), or more specific wrappers in the places in blink that really care about this?This is all very subtle but let me try to explain. (hiroshige@ could probably give more details and concrete examples)Having a move-only closure helps to avoid leaking a reference on the calling thread after postTask(). Or having a move-only wrapper for WTF::String (and all such racy classes) could be also useful. But this only solves one aspect, in order to safely pass a WTF::String to another thread one also needs to create an isolated copy of WTF::String which doesn't share any ref-counting with existing String objects. (I think this answers to one of your questions)And one more thing to note, the same thing needs to apply to all objects that contain WTF::String in any of their members. So if one wants to bind KURL for running a method on another thread, we first need to create an isolated copy of KURL without leaking any reference after postTask because KURL contains WTF::String. Ditto if one wants to bind an object that contains KURL.So the biggest problem is, even if we have move-only callback, the caller needs to choose the right one and does the right thing, and it's almost impractical to assume that everyone understands all these well and does the right thing (TM).So what hiroshige@ did in Blink was to make WTF::bind() always return move-only (so that no one can leave an unexpected reference after postTask), and to introduce a new WTF::bind() for cross-thread version which does this all (so that all cross-thread post tasking could be automatically taken care of, while keeping the same-thread post tasking to work as is with full benefit of ref-counting for performance).As far as I can tell, the thread safe bind uses WTF::bind, but it just makes deep copies of objects that are known to be ref counted but not thread safe (such as KURL and String). This thread safe bind can still remain, but use base::Bind internally instead, right? Assuming of course that base::Bind has a version that returns a move only callback. So, if bind returns a move only callback of a different type like base::MoveOnlyCallback for lack of a better name, then PostTask would also have to deal with the fact that there's a move only callback as well as a copy-able one and possibly do asserts in the copy-able version to ensure that it's not going cross threads.Additionally, I don't think there's any checks in place to enforce that people actually use threadSafeBind instead of regular WTF::bind with objects that are not thread safe ref counted. That is, at least I couldn't find any of these checks. So, even if you use move only callbacks, there's still no guarantee that both problems are solved. One needs to ensure that threadSafeBind is used instead WTF::bind
On Thu, Oct 15, 2015 at 2:50 PM, Vladimir Levin <vmp...@google.com> wrote:On Thu, Oct 15, 2015 at 1:18 PM, Dana Jansens <dan...@chromium.org> wrote:On Mon, Oct 12, 2015 at 7:18 PM, Kinuko Yasuda <kin...@chromium.org> wrote:On Tue, Oct 13, 2015 at 8:52 AM, Dana Jansens <dan...@chromium.org> wrote:On Mon, Oct 12, 2015 at 4:42 PM, Daniel Cheng <dch...@chromium.org> wrote:The problems with WTF::String stem from the fact that it is internally refcounted, but the refcounting is not thread-safe. https://docs.google.com/document/d/17qforp6RQ6GIy3Jr5qA04krKTyfZe3LdPQVTjYHyFpA/edit has the details (sorry, I think this is google.com only).Oh :( This is a huge problem in chromium too FWIW. Any time you stick a RefCountedThreadSafe object into a Closure and PostTask it, you have no idea where it will be deleted. Often people want to do some thread-specific thing in the destructor and they just.. can't. So the (unfortunately) common pattern is to PostTask to the right thread from the destructor, but by then it's too late to handle the case that PostTask can fail.. so you can just leak/fail to destruct.WTF::String is NOT thread-safe ref-counted, yet it's used in cross-thread post tasking (partly because we have no other thread-safe string representation in Blink other than std::string), so the situation is probably worse.Hypothetically.. would making Callback move-only solve all of the problems here? I'm not sure how intractable that would be but it could help a lot in Chrome probably.There's some mention of WTF callbacks being one-shot which differs from Base. But what impact does this have on WTF::String? We could perhaps provide a wrapper around a base::Callback like WTF::OneShotCallback that crashes if you try call it twice or something (we have a similar thing in cc::SingleReleaseCallback), or more specific wrappers in the places in blink that really care about this?This is all very subtle but let me try to explain. (hiroshige@ could probably give more details and concrete examples)Having a move-only closure helps to avoid leaking a reference on the calling thread after postTask(). Or having a move-only wrapper for WTF::String (and all such racy classes) could be also useful. But this only solves one aspect, in order to safely pass a WTF::String to another thread one also needs to create an isolated copy of WTF::String which doesn't share any ref-counting with existing String objects. (I think this answers to one of your questions)And one more thing to note, the same thing needs to apply to all objects that contain WTF::String in any of their members. So if one wants to bind KURL for running a method on another thread, we first need to create an isolated copy of KURL without leaking any reference after postTask because KURL contains WTF::String. Ditto if one wants to bind an object that contains KURL.So the biggest problem is, even if we have move-only callback, the caller needs to choose the right one and does the right thing, and it's almost impractical to assume that everyone understands all these well and does the right thing (TM).So what hiroshige@ did in Blink was to make WTF::bind() always return move-only (so that no one can leave an unexpected reference after postTask), and to introduce a new WTF::bind() for cross-thread version which does this all (so that all cross-thread post tasking could be automatically taken care of, while keeping the same-thread post tasking to work as is with full benefit of ref-counting for performance).As far as I can tell, the thread safe bind uses WTF::bind, but it just makes deep copies of objects that are known to be ref counted but not thread safe (such as KURL and String). This thread safe bind can still remain, but use base::Bind internally instead, right? Assuming of course that base::Bind has a version that returns a move only callback. So, if bind returns a move only callback of a different type like base::MoveOnlyCallback for lack of a better name, then PostTask would also have to deal with the fact that there's a move only callback as well as a copy-able one and possibly do asserts in the copy-able version to ensure that it's not going cross threads.Additionally, I don't think there's any checks in place to enforce that people actually use threadSafeBind instead of regular WTF::bind with objects that are not thread safe ref counted. That is, at least I couldn't find any of these checks. So, even if you use move only callbacks, there's still no guarantee that both problems are solved. One needs to ensure that threadSafeBind is used instead WTF::bind
Was your hope to replace blink::threadSafeBind (in platform/) with uses of base::Bind? Or just to replace WTF::bind() (in wtf/) with base?The former has type-specfic deep copies for every type that can be posted, which isn't super scalable and doesn't seem well suited to base, and is probably in the right place where it is (modulo completely different ideas).
The document lists two problems. AIUI, move-only Callback solves one, deep copies in blink::threadSafeBind solves the other. Either solution is not good enough without the other, right? So we still want to make callers in blink use blink::threadSafeBind where it makes sense (for isolatedCopy()). Then if threadSafeBind returned a base::MoveOnlyCallback, we'd have both problems solved?
I can imagine our PostTask methods DCHECKing that non-MoveOnly callbacks are only posted to the same thread. It may or may not be possible, but that seems like strictly more safety over what blink is providing now, is that right?
Hello thread! I'm wondering if there's been any progress on these fronts lately, and otherwise if there's some way I or others can help make progress.Specifically:
- Does the Blink team want to move forward with mass annotation for safer cross-thread object handling? Do you need help getting it done (i.e. moar people typing CLs)?
- Is there some material explaining specifically how base::Callback needs to change to be safer? Anyone working on it implementation changes?
- From earlier in the thread: anyone looked/looking at making PostTask enforce that copyable callbacks are called on the posting thread? (FWIW I'm not sure this is something that really makes sense to do since it is hard to implement and IIUC would be trivial to circumvent, accidentally or otherwise.)
- Is there a working draft of an overall plan from esprehn@ available yet?