You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by "Stephan Voigt (JIRA)" <de...@myfaces.apache.org> on 2009/01/27 16:31:02 UTC
[jira] Created: (PORTLETBRIDGE-58) Race condition BridgeImpl in
multi-threaded environment
Race condition BridgeImpl in multi-threaded environment
-------------------------------------------------------
Key: PORTLETBRIDGE-58
URL: https://issues.apache.org/jira/browse/PORTLETBRIDGE-58
Project: MyFaces Portlet Bridge
Issue Type: Bug
Components: Impl
Affects Versions: 1.0.0-beta, 1.0.0-alpha-3
Environment: Pluto 1.1.5
JSF 1.2 / RI
Reporter: Stephan Voigt
Priority: Critical
The implementation in BridgeImpl delegates the calls to the JSF Phases to a initially created LifeCycle instance (member of BrideImpl).
In order to implement the LifeCycle acc. JSR-301 all JSF-Phases except RENDER_RESPONSE are suppressed using a PhaseListener which calls renderResponse on the current FacesContext, so that the further phase processing stops.
The PhaseListener is registered and unregistered in doFacesRender() during a render request.
The problem: when executed in multiple threads, calls to doFacesRequest (ActionRequests) use the same LifeCycle instance, which causes a race condition. The processing of the portlet action will canceled for that request.
We reproduced that behavior in our environment (JSF-RI, Pluto 1.1.5, PortletBridge 1.0.0-alpha-3, beta1) using loadtests with 3 or more parallel threads.
The problematic code-passage in BridgeImpl (see addPhaseListener and removePhaseListener calls):
...
private void doFacesRender(RenderRequest request, RenderResponse response, FacesContext context, Lifecycle lifecycle, String scopeId,
List <String> preExistingAttributes)
throws BridgeException, BridgeUninitializedException, NullPointerException
{
...
if (context.getViewRoot() == null)
{
// add self as PhaseListener to prevent action phases from
// executing
lifecycle.addPhaseListener(this);
try
{
lifecycle.execute(context);
}
catch (Exception e)
{
....
}
finally
{
lifecycle.removePhaseListener(this);
}
....
In order to solve the problem, we patched the BridgeImpl class in that way it uses a static configuration for the LifeCycle instance with one enabled Phase-Listener. The decision when the request processing should be stopped (via calling renderResponse() on the FacesContext) is handled using a ThreadLocal flag indicating the mode (Action/Render) of the current BridgeRequest.
Please let me know, if I should provide a corresponding patch set (based on the beta-1 code line) or if the problem will be solved in a different manner.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Updated: (PORTLETBRIDGE-58) Race condition BridgeImpl in
multi-threaded environment
Posted by "Michael Freedman (JIRA)" <de...@myfaces.apache.org>.
[ https://issues.apache.org/jira/browse/PORTLETBRIDGE-58?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Michael Freedman updated PORTLETBRIDGE-58:
------------------------------------------
Resolution: Fixed
Fix Version/s: 2.0.0
1.0.0
Status: Resolved (was: Patch Available)
Fixed by removing use of the shared private data member holding onto the Lifecycle object. Instead its created per request.
> Race condition BridgeImpl in multi-threaded environment
> -------------------------------------------------------
>
> Key: PORTLETBRIDGE-58
> URL: https://issues.apache.org/jira/browse/PORTLETBRIDGE-58
> Project: MyFaces Portlet Bridge
> Issue Type: Bug
> Components: Impl
> Affects Versions: 1.0.0-alpha-3, 1.0.0-beta
> Environment: Pluto 1.1.5
> JSF 1.2 / RI
> Reporter: Stephan Voigt
> Assignee: Michael Freedman
> Priority: Critical
> Fix For: 1.0.0, 2.0.0
>
> Attachments: jira_58_and_61.patch
>
>
> The implementation in BridgeImpl delegates the calls to the JSF Phases to a initially created LifeCycle instance (member of BrideImpl).
> In order to implement the LifeCycle acc. JSR-301 all JSF-Phases except RENDER_RESPONSE are suppressed using a PhaseListener which calls renderResponse on the current FacesContext, so that the further phase processing stops.
> The PhaseListener is registered and unregistered in doFacesRender() during a render request.
> The problem: when executed in multiple threads, calls to doFacesRequest (ActionRequests) use the same LifeCycle instance, which causes a race condition. The processing of the portlet action will canceled for that request.
> We reproduced that behavior in our environment (JSF-RI, Pluto 1.1.5, PortletBridge 1.0.0-alpha-3, beta1) using loadtests with 3 or more parallel threads.
> The problematic code-passage in BridgeImpl (see addPhaseListener and removePhaseListener calls):
> ...
> private void doFacesRender(RenderRequest request, RenderResponse response, FacesContext context, Lifecycle lifecycle, String scopeId,
> List <String> preExistingAttributes)
> throws BridgeException, BridgeUninitializedException, NullPointerException
> {
> ...
> if (context.getViewRoot() == null)
> {
> // add self as PhaseListener to prevent action phases from
> // executing
> lifecycle.addPhaseListener(this);
> try
> {
> lifecycle.execute(context);
> }
> catch (Exception e)
> {
> ....
> }
> finally
> {
> lifecycle.removePhaseListener(this);
> }
> ....
> In order to solve the problem, we patched the BridgeImpl class in that way it uses a static configuration for the LifeCycle instance with one enabled Phase-Listener. The decision when the request processing should be stopped (via calling renderResponse() on the FacesContext) is handled using a ThreadLocal flag indicating the mode (Action/Render) of the current BridgeRequest.
> Please let me know, if I should provide a corresponding patch set (based on the beta-1 code line) or if the problem will be solved in a different manner.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (PORTLETBRIDGE-58) Race condition BridgeImpl in
multi-threaded environment
Posted by "Jondean Haley (JIRA)" <de...@myfaces.apache.org>.
[ https://issues.apache.org/jira/browse/PORTLETBRIDGE-58?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12668320#action_12668320 ]
Jondean Haley commented on PORTLETBRIDGE-58:
--------------------------------------------
Hi Stephan,
Good find on this race condition. We should stay consistent on the use of request attributes or ThreadLocals as per-thread flags, and attributes have been the design so far.
The request attribute marking the type of request is set early in the BridgeImpl doFacesRequest() methods:
request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, Bridge.PortletPhase.ACTION_PHASE);
So PORTLET_LIFECYCLE_PHASE can be checked in place of your proposed ThreadLocal flag.
Could you please add a comment with your code snippet for the static design you mention.
Thanks,
Jondean.
> Race condition BridgeImpl in multi-threaded environment
> -------------------------------------------------------
>
> Key: PORTLETBRIDGE-58
> URL: https://issues.apache.org/jira/browse/PORTLETBRIDGE-58
> Project: MyFaces Portlet Bridge
> Issue Type: Bug
> Components: Impl
> Affects Versions: 1.0.0-alpha-3, 1.0.0-beta
> Environment: Pluto 1.1.5
> JSF 1.2 / RI
> Reporter: Stephan Voigt
> Priority: Critical
>
> The implementation in BridgeImpl delegates the calls to the JSF Phases to a initially created LifeCycle instance (member of BrideImpl).
> In order to implement the LifeCycle acc. JSR-301 all JSF-Phases except RENDER_RESPONSE are suppressed using a PhaseListener which calls renderResponse on the current FacesContext, so that the further phase processing stops.
> The PhaseListener is registered and unregistered in doFacesRender() during a render request.
> The problem: when executed in multiple threads, calls to doFacesRequest (ActionRequests) use the same LifeCycle instance, which causes a race condition. The processing of the portlet action will canceled for that request.
> We reproduced that behavior in our environment (JSF-RI, Pluto 1.1.5, PortletBridge 1.0.0-alpha-3, beta1) using loadtests with 3 or more parallel threads.
> The problematic code-passage in BridgeImpl (see addPhaseListener and removePhaseListener calls):
> ...
> private void doFacesRender(RenderRequest request, RenderResponse response, FacesContext context, Lifecycle lifecycle, String scopeId,
> List <String> preExistingAttributes)
> throws BridgeException, BridgeUninitializedException, NullPointerException
> {
> ...
> if (context.getViewRoot() == null)
> {
> // add self as PhaseListener to prevent action phases from
> // executing
> lifecycle.addPhaseListener(this);
> try
> {
> lifecycle.execute(context);
> }
> catch (Exception e)
> {
> ....
> }
> finally
> {
> lifecycle.removePhaseListener(this);
> }
> ....
> In order to solve the problem, we patched the BridgeImpl class in that way it uses a static configuration for the LifeCycle instance with one enabled Phase-Listener. The decision when the request processing should be stopped (via calling renderResponse() on the FacesContext) is handled using a ThreadLocal flag indicating the mode (Action/Render) of the current BridgeRequest.
> Please let me know, if I should provide a corresponding patch set (based on the beta-1 code line) or if the problem will be solved in a different manner.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Updated: (PORTLETBRIDGE-58) Race condition BridgeImpl in
multi-threaded environment
Posted by "Michael Freedman (JIRA)" <de...@myfaces.apache.org>.
[ https://issues.apache.org/jira/browse/PORTLETBRIDGE-58?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Michael Freedman updated PORTLETBRIDGE-58:
------------------------------------------
Status: Patch Available (was: Open)
> Race condition BridgeImpl in multi-threaded environment
> -------------------------------------------------------
>
> Key: PORTLETBRIDGE-58
> URL: https://issues.apache.org/jira/browse/PORTLETBRIDGE-58
> Project: MyFaces Portlet Bridge
> Issue Type: Bug
> Components: Impl
> Affects Versions: 1.0.0-alpha-3, 1.0.0-beta
> Environment: Pluto 1.1.5
> JSF 1.2 / RI
> Reporter: Stephan Voigt
> Priority: Critical
>
> The implementation in BridgeImpl delegates the calls to the JSF Phases to a initially created LifeCycle instance (member of BrideImpl).
> In order to implement the LifeCycle acc. JSR-301 all JSF-Phases except RENDER_RESPONSE are suppressed using a PhaseListener which calls renderResponse on the current FacesContext, so that the further phase processing stops.
> The PhaseListener is registered and unregistered in doFacesRender() during a render request.
> The problem: when executed in multiple threads, calls to doFacesRequest (ActionRequests) use the same LifeCycle instance, which causes a race condition. The processing of the portlet action will canceled for that request.
> We reproduced that behavior in our environment (JSF-RI, Pluto 1.1.5, PortletBridge 1.0.0-alpha-3, beta1) using loadtests with 3 or more parallel threads.
> The problematic code-passage in BridgeImpl (see addPhaseListener and removePhaseListener calls):
> ...
> private void doFacesRender(RenderRequest request, RenderResponse response, FacesContext context, Lifecycle lifecycle, String scopeId,
> List <String> preExistingAttributes)
> throws BridgeException, BridgeUninitializedException, NullPointerException
> {
> ...
> if (context.getViewRoot() == null)
> {
> // add self as PhaseListener to prevent action phases from
> // executing
> lifecycle.addPhaseListener(this);
> try
> {
> lifecycle.execute(context);
> }
> catch (Exception e)
> {
> ....
> }
> finally
> {
> lifecycle.removePhaseListener(this);
> }
> ....
> In order to solve the problem, we patched the BridgeImpl class in that way it uses a static configuration for the LifeCycle instance with one enabled Phase-Listener. The decision when the request processing should be stopped (via calling renderResponse() on the FacesContext) is handled using a ThreadLocal flag indicating the mode (Action/Render) of the current BridgeRequest.
> Please let me know, if I should provide a corresponding patch set (based on the beta-1 code line) or if the problem will be solved in a different manner.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.