You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tuscany.apache.org by "Scott Kurz (JIRA)" <de...@tuscany.apache.org> on 2008/10/06 20:43:44 UTC
[jira] Created: (TUSCANY-2630) memleak as RuntimeWireImpl callback
cachedWire ref leaks due to clone() impl
memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone() impl
----------------------------------------------------------------------------
Key: TUSCANY-2630
URL: https://issues.apache.org/jira/browse/TUSCANY-2630
Project: Tuscany
Issue Type: Bug
Components: Java SCA Core Runtime
Reporter: Scott Kurz
We can end up with an unbounded chain of RuntimeWireImpls because of the way the 'cachedWire' field is handled to cache a callback wire.
The problem arises with a sequence like:
1) Thread A calls CallbackReferenceImpl.getCallbackWire(), which results in a wire.clone() and then the boundWire is "cached" via:
((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
2) Thread B calls the same method on the same 'wire' instance, but because the cachedWire is in-use, it does its own wire.clone(),
making a shallow copy of wire's 'cachedWire'.
3) Only now does Thread A finish and call: ((RuntimeWireImpl)wire).releaseWire(); (Nothing special happens here. I'm just pointing out
that since 2) happened first, the cached object was in-use and a new clone was made.
4) When Thread B gets to the end of RuntimeWireImpl.cloneAndBind() it calls:
((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
The net result is that the original wire has a ref, 'cachedWire' to the clone made in Thread B, which in turn has a ref to the clone made from Thread A.
This illustrates the problem, as this can recursively grow unbounded.
---------
A simple solution would seem to be to null out the 'cachedWire' field towards the end of RuntimeWireImpl.clone(). Maybe there's an even better one.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
Re: [jira] Commented: (TUSCANY-2630) memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone() impl
Posted by Simon Laws <si...@googlemail.com>.
On Tue, Oct 7, 2008 at 2:17 PM, Scott Kurz (JIRA) <de...@tuscany.apache.org>wrote:
>
> [
> https://issues.apache.org/jira/browse/TUSCANY-2630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12637471#action_12637471]
>
> Scott Kurz commented on TUSCANY-2630:
> -------------------------------------
>
> Thanks for taking a look. Not understanding this code real well, I have
> to take it for granted that we have a good reason for not sharing the
> callback wire across threads, (though I was half-wondering if that might
> have been an old assumption that someone might realize is no longer needed).
>
> I don't know how to contribute a test showing this timing-dependent issue;
> I have to use the debugger to step through to recreate. However, I would
> say I've confirmed this fixes the leak in my environment.
>
>
>
> > memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone()
> impl
> >
> ----------------------------------------------------------------------------
> >
> > Key: TUSCANY-2630
> > URL: https://issues.apache.org/jira/browse/TUSCANY-2630
> > Project: Tuscany
> > Issue Type: Bug
> > Components: Java SCA Core Runtime
> > Reporter: Scott Kurz
> >
> > We can end up with an unbounded chain of RuntimeWireImpls because of the
> way the 'cachedWire' field is handled to cache a callback wire.
> > The problem arises with a sequence like:
> > 1) Thread A calls CallbackReferenceImpl.getCallbackWire(), which results
> in a wire.clone() and then the boundWire is "cached" via:
> > ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> > 2) Thread B calls the same method on the same 'wire' instance, but
> because the cachedWire is in-use, it does its own wire.clone(),
> > making a shallow copy of wire's 'cachedWire'.
> > 3) Only now does Thread A finish and call:
> ((RuntimeWireImpl)wire).releaseWire(); (Nothing special happens here.
> I'm just pointing out
> > that since 2) happened first, the cached object was in-use and a new
> clone was made.
> > 4) When Thread B gets to the end of RuntimeWireImpl.cloneAndBind() it
> calls:
> > ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> > The net result is that the original wire has a ref, 'cachedWire' to the
> clone made in Thread B, which in turn has a ref to the clone made from
> Thread A.
> > This illustrates the problem, as this can recursively grow unbounded.
> > ---------
> > A simple solution would seem to be to null out the 'cachedWire' field
> towards the end of RuntimeWireImpl.clone(). Maybe there's an even better
> one.
>
> --
> This message is automatically generated by JIRA.
> -
> You can reply to this email to add a comment to the issue online.
>
IIRC it's because the callbacks for different threads can (will) have
different destinations and hence the wires are configured differently.
Simon
[jira] Commented: (TUSCANY-2630) memleak as RuntimeWireImpl
callback cachedWire ref leaks due to clone() impl
Posted by "Scott Kurz (JIRA)" <de...@tuscany.apache.org>.
[ https://issues.apache.org/jira/browse/TUSCANY-2630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12638070#action_12638070 ]
Scott Kurz commented on TUSCANY-2630:
-------------------------------------
Fixed in trunk in r702984.
> memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone() impl
> ----------------------------------------------------------------------------
>
> Key: TUSCANY-2630
> URL: https://issues.apache.org/jira/browse/TUSCANY-2630
> Project: Tuscany
> Issue Type: Bug
> Components: Java SCA Core Runtime
> Reporter: Scott Kurz
>
> We can end up with an unbounded chain of RuntimeWireImpls because of the way the 'cachedWire' field is handled to cache a callback wire.
> The problem arises with a sequence like:
> 1) Thread A calls CallbackReferenceImpl.getCallbackWire(), which results in a wire.clone() and then the boundWire is "cached" via:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> 2) Thread B calls the same method on the same 'wire' instance, but because the cachedWire is in-use, it does its own wire.clone(),
> making a shallow copy of wire's 'cachedWire'.
> 3) Only now does Thread A finish and call: ((RuntimeWireImpl)wire).releaseWire(); (Nothing special happens here. I'm just pointing out
> that since 2) happened first, the cached object was in-use and a new clone was made.
> 4) When Thread B gets to the end of RuntimeWireImpl.cloneAndBind() it calls:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> The net result is that the original wire has a ref, 'cachedWire' to the clone made in Thread B, which in turn has a ref to the clone made from Thread A.
> This illustrates the problem, as this can recursively grow unbounded.
> ---------
> A simple solution would seem to be to null out the 'cachedWire' field towards the end of RuntimeWireImpl.clone(). Maybe there's an even better one.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (TUSCANY-2630) memleak as RuntimeWireImpl
callback cachedWire ref leaks due to clone() impl
Posted by "Simon Laws (JIRA)" <de...@tuscany.apache.org>.
[ https://issues.apache.org/jira/browse/TUSCANY-2630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12640515#action_12640515 ]
Simon Laws commented on TUSCANY-2630:
-------------------------------------
committed to 1.3.3 at revision: 705595
> memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone() impl
> ----------------------------------------------------------------------------
>
> Key: TUSCANY-2630
> URL: https://issues.apache.org/jira/browse/TUSCANY-2630
> Project: Tuscany
> Issue Type: Bug
> Components: Java SCA Core Runtime
> Reporter: Scott Kurz
> Fix For: Java SCA-1.3.3
>
>
> We can end up with an unbounded chain of RuntimeWireImpls because of the way the 'cachedWire' field is handled to cache a callback wire.
> The problem arises with a sequence like:
> 1) Thread A calls CallbackReferenceImpl.getCallbackWire(), which results in a wire.clone() and then the boundWire is "cached" via:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> 2) Thread B calls the same method on the same 'wire' instance, but because the cachedWire is in-use, it does its own wire.clone(),
> making a shallow copy of wire's 'cachedWire'.
> 3) Only now does Thread A finish and call: ((RuntimeWireImpl)wire).releaseWire(); (Nothing special happens here. I'm just pointing out
> that since 2) happened first, the cached object was in-use and a new clone was made.
> 4) When Thread B gets to the end of RuntimeWireImpl.cloneAndBind() it calls:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> The net result is that the original wire has a ref, 'cachedWire' to the clone made in Thread B, which in turn has a ref to the clone made from Thread A.
> This illustrates the problem, as this can recursively grow unbounded.
> ---------
> A simple solution would seem to be to null out the 'cachedWire' field towards the end of RuntimeWireImpl.clone(). Maybe there's an even better one.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Resolved: (TUSCANY-2630) memleak as RuntimeWireImpl callback
cachedWire ref leaks due to clone() impl
Posted by "Scott Kurz (JIRA)" <de...@tuscany.apache.org>.
[ https://issues.apache.org/jira/browse/TUSCANY-2630?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Scott Kurz resolved TUSCANY-2630.
---------------------------------
Resolution: Fixed
Fix Version/s: Java-SCA-Next
> memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone() impl
> ----------------------------------------------------------------------------
>
> Key: TUSCANY-2630
> URL: https://issues.apache.org/jira/browse/TUSCANY-2630
> Project: Tuscany
> Issue Type: Bug
> Components: Java SCA Core Runtime
> Reporter: Scott Kurz
> Fix For: Java-SCA-Next
>
>
> We can end up with an unbounded chain of RuntimeWireImpls because of the way the 'cachedWire' field is handled to cache a callback wire.
> The problem arises with a sequence like:
> 1) Thread A calls CallbackReferenceImpl.getCallbackWire(), which results in a wire.clone() and then the boundWire is "cached" via:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> 2) Thread B calls the same method on the same 'wire' instance, but because the cachedWire is in-use, it does its own wire.clone(),
> making a shallow copy of wire's 'cachedWire'.
> 3) Only now does Thread A finish and call: ((RuntimeWireImpl)wire).releaseWire(); (Nothing special happens here. I'm just pointing out
> that since 2) happened first, the cached object was in-use and a new clone was made.
> 4) When Thread B gets to the end of RuntimeWireImpl.cloneAndBind() it calls:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> The net result is that the original wire has a ref, 'cachedWire' to the clone made in Thread B, which in turn has a ref to the clone made from Thread A.
> This illustrates the problem, as this can recursively grow unbounded.
> ---------
> A simple solution would seem to be to null out the 'cachedWire' field towards the end of RuntimeWireImpl.clone(). Maybe there's an even better one.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (TUSCANY-2630) memleak as RuntimeWireImpl
callback cachedWire ref leaks due to clone() impl
Posted by "ant elder (JIRA)" <de...@tuscany.apache.org>.
[ https://issues.apache.org/jira/browse/TUSCANY-2630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12637414#action_12637414 ]
ant elder commented on TUSCANY-2630:
------------------------------------
The simple solution you propose looks ok to me but other than ensuring the build still works it would be hard for me to test as its quite a complicated scenario. Any chance you could provide a testcase demonstrating the issue? If its a lot of work to make your test contributable how about you just make the change locally yourself and confirm it fixes the leak in your environment?
> memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone() impl
> ----------------------------------------------------------------------------
>
> Key: TUSCANY-2630
> URL: https://issues.apache.org/jira/browse/TUSCANY-2630
> Project: Tuscany
> Issue Type: Bug
> Components: Java SCA Core Runtime
> Reporter: Scott Kurz
>
> We can end up with an unbounded chain of RuntimeWireImpls because of the way the 'cachedWire' field is handled to cache a callback wire.
> The problem arises with a sequence like:
> 1) Thread A calls CallbackReferenceImpl.getCallbackWire(), which results in a wire.clone() and then the boundWire is "cached" via:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> 2) Thread B calls the same method on the same 'wire' instance, but because the cachedWire is in-use, it does its own wire.clone(),
> making a shallow copy of wire's 'cachedWire'.
> 3) Only now does Thread A finish and call: ((RuntimeWireImpl)wire).releaseWire(); (Nothing special happens here. I'm just pointing out
> that since 2) happened first, the cached object was in-use and a new clone was made.
> 4) When Thread B gets to the end of RuntimeWireImpl.cloneAndBind() it calls:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> The net result is that the original wire has a ref, 'cachedWire' to the clone made in Thread B, which in turn has a ref to the clone made from Thread A.
> This illustrates the problem, as this can recursively grow unbounded.
> ---------
> A simple solution would seem to be to null out the 'cachedWire' field towards the end of RuntimeWireImpl.clone(). Maybe there's an even better one.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (TUSCANY-2630) memleak as RuntimeWireImpl
callback cachedWire ref leaks due to clone() impl
Posted by "Scott Kurz (JIRA)" <de...@tuscany.apache.org>.
[ https://issues.apache.org/jira/browse/TUSCANY-2630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12637471#action_12637471 ]
Scott Kurz commented on TUSCANY-2630:
-------------------------------------
Thanks for taking a look. Not understanding this code real well, I have to take it for granted that we have a good reason for not sharing the callback wire across threads, (though I was half-wondering if that might have been an old assumption that someone might realize is no longer needed).
I don't know how to contribute a test showing this timing-dependent issue; I have to use the debugger to step through to recreate. However, I would say I've confirmed this fixes the leak in my environment.
> memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone() impl
> ----------------------------------------------------------------------------
>
> Key: TUSCANY-2630
> URL: https://issues.apache.org/jira/browse/TUSCANY-2630
> Project: Tuscany
> Issue Type: Bug
> Components: Java SCA Core Runtime
> Reporter: Scott Kurz
>
> We can end up with an unbounded chain of RuntimeWireImpls because of the way the 'cachedWire' field is handled to cache a callback wire.
> The problem arises with a sequence like:
> 1) Thread A calls CallbackReferenceImpl.getCallbackWire(), which results in a wire.clone() and then the boundWire is "cached" via:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> 2) Thread B calls the same method on the same 'wire' instance, but because the cachedWire is in-use, it does its own wire.clone(),
> making a shallow copy of wire's 'cachedWire'.
> 3) Only now does Thread A finish and call: ((RuntimeWireImpl)wire).releaseWire(); (Nothing special happens here. I'm just pointing out
> that since 2) happened first, the cached object was in-use and a new clone was made.
> 4) When Thread B gets to the end of RuntimeWireImpl.cloneAndBind() it calls:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> The net result is that the original wire has a ref, 'cachedWire' to the clone made in Thread B, which in turn has a ref to the clone made from Thread A.
> This illustrates the problem, as this can recursively grow unbounded.
> ---------
> A simple solution would seem to be to null out the 'cachedWire' field towards the end of RuntimeWireImpl.clone(). Maybe there's an even better one.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (TUSCANY-2630) memleak as RuntimeWireImpl
callback cachedWire ref leaks due to clone() impl
Posted by "Simon Nash (JIRA)" <de...@tuscany.apache.org>.
[ https://issues.apache.org/jira/browse/TUSCANY-2630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12638098#action_12638098 ]
Simon Nash commented on TUSCANY-2630:
-------------------------------------
Apologies for not considering the multi-threaded case when I wrote this caching code. The fix seems fine. Callback wires can't be shared between callback invocations because there is code in the callback path that modifies the wire and/or its contents. The cache was intended to avoid the need to create a new clone on every callback invocation between the same pair of components. It will be less effective in this multi-threaded case than in a single-threaded scenario, but it should still be better than not doing any caching.
> memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone() impl
> ----------------------------------------------------------------------------
>
> Key: TUSCANY-2630
> URL: https://issues.apache.org/jira/browse/TUSCANY-2630
> Project: Tuscany
> Issue Type: Bug
> Components: Java SCA Core Runtime
> Reporter: Scott Kurz
>
> We can end up with an unbounded chain of RuntimeWireImpls because of the way the 'cachedWire' field is handled to cache a callback wire.
> The problem arises with a sequence like:
> 1) Thread A calls CallbackReferenceImpl.getCallbackWire(), which results in a wire.clone() and then the boundWire is "cached" via:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> 2) Thread B calls the same method on the same 'wire' instance, but because the cachedWire is in-use, it does its own wire.clone(),
> making a shallow copy of wire's 'cachedWire'.
> 3) Only now does Thread A finish and call: ((RuntimeWireImpl)wire).releaseWire(); (Nothing special happens here. I'm just pointing out
> that since 2) happened first, the cached object was in-use and a new clone was made.
> 4) When Thread B gets to the end of RuntimeWireImpl.cloneAndBind() it calls:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> The net result is that the original wire has a ref, 'cachedWire' to the clone made in Thread B, which in turn has a ref to the clone made from Thread A.
> This illustrates the problem, as this can recursively grow unbounded.
> ---------
> A simple solution would seem to be to null out the 'cachedWire' field towards the end of RuntimeWireImpl.clone(). Maybe there's an even better one.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Updated: (TUSCANY-2630) memleak as RuntimeWireImpl callback
cachedWire ref leaks due to clone() impl
Posted by "Simon Laws (JIRA)" <de...@tuscany.apache.org>.
[ https://issues.apache.org/jira/browse/TUSCANY-2630?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Simon Laws updated TUSCANY-2630:
--------------------------------
Fix Version/s: (was: Java-SCA-Next)
Java SCA-1.3.3
I want to put this in 1.3.3 also in case it comes up
> memleak as RuntimeWireImpl callback cachedWire ref leaks due to clone() impl
> ----------------------------------------------------------------------------
>
> Key: TUSCANY-2630
> URL: https://issues.apache.org/jira/browse/TUSCANY-2630
> Project: Tuscany
> Issue Type: Bug
> Components: Java SCA Core Runtime
> Reporter: Scott Kurz
> Fix For: Java SCA-1.3.3
>
>
> We can end up with an unbounded chain of RuntimeWireImpls because of the way the 'cachedWire' field is handled to cache a callback wire.
> The problem arises with a sequence like:
> 1) Thread A calls CallbackReferenceImpl.getCallbackWire(), which results in a wire.clone() and then the boundWire is "cached" via:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> 2) Thread B calls the same method on the same 'wire' instance, but because the cachedWire is in-use, it does its own wire.clone(),
> making a shallow copy of wire's 'cachedWire'.
> 3) Only now does Thread A finish and call: ((RuntimeWireImpl)wire).releaseWire(); (Nothing special happens here. I'm just pointing out
> that since 2) happened first, the cached object was in-use and a new clone was made.
> 4) When Thread B gets to the end of RuntimeWireImpl.cloneAndBind() it calls:
> ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire);
> The net result is that the original wire has a ref, 'cachedWire' to the clone made in Thread B, which in turn has a ref to the clone made from Thread A.
> This illustrates the problem, as this can recursively grow unbounded.
> ---------
> A simple solution would seem to be to null out the 'cachedWire' field towards the end of RuntimeWireImpl.clone(). Maybe there's an even better one.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.