ICEfaces
  1. ICEfaces
  2. ICE-2615

ExternalContext parameter maps not thread safe leads to deadlock or other symptoms

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.7DR#3
    • Fix Version/s: 1.7Beta1, 1.7
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      ICEfaces

      Description

      The problem is that the requestParameter maps in the ExternalContext (BridgeExternalContext and ServletExternalContext) are not protected by synchronization.

      The example application I had included several text input fields each triggering an event on loss of focus. Holding the tab key down generates a rapid stream of requests to the server, all intended for the same ViewRoot, (and ExternalContext instance). The stream of requests is so rapid that a thread (eg. HTTP-1 ) is in the renderResponse phase while the next request (eg. via HTTP-2) has arrived and is progressing through the MainServlet. The problem arises in the ViewBoundServer which calls update on the ExternalContext instance without any synchronization.

      At the very least, this puts the values in the request parameter maps at risk of concurrent modification by the incoming thread while the current thread is executing or rendering in the JSF lifecycle. In my example, there's a very short window of time when the new request parameter maps don't have any values at all, and occasionally (extremely rarely actually), Spring webflow would not unlock the webflow properly (since the webflow key could wasn't found in the externalContext.getRequestParameter map, leading to a complete server deadlock.

      Note that it's possible to construct the new maps and copy values into them, and then swap references to them which alleviates the problem with my missing parameters (since the request continually contains the same parameters, any version will do) but that doesn't fix the problem if the request parameters are changing with each new request potentially overwriting parameters from the immediately previous request.

      I think we need to move the synchronization protection to a position that protects all contents of the View for the duration of any single request.

        Activity

        Hide
        Greg Dick added a comment -

        The synchronization on partial submit requests was at the ReceiveSendUpdates class level. However, modifications to the ExternalContext requestParameterMap and requestMap member variables could be done outside this protection.

        The result of this was crosstalk between closely arriving partial submit requests. Something that is easily achieved by tabbing out of a series of inputText components with partialSubmit enabled.

        I moved the synchronization up to the ViewBoundServer class, where these maps are now protected.

        Note that there is still a fundamental and serious issue with server initiated rendering in conjunction with Spring Webflow 1.0.x. When server initiated rendering thread calls execute and starts the JSF lifecycle, webflow finds the executorKey in the UIViewRoot. However when it comes time to clean up, in the post RenderResponse phase listener, it tries to find the same key in the ExternalContext.requestMap. Aside from not being protected by the above described synchronization because it doesn't enter through the servlet path, the state of the request maps is non-deterministic, resulting in potential deadlocks, or potentially difficult to find race conditions.

        Show
        Greg Dick added a comment - The synchronization on partial submit requests was at the ReceiveSendUpdates class level. However, modifications to the ExternalContext requestParameterMap and requestMap member variables could be done outside this protection. The result of this was crosstalk between closely arriving partial submit requests. Something that is easily achieved by tabbing out of a series of inputText components with partialSubmit enabled. I moved the synchronization up to the ViewBoundServer class, where these maps are now protected. Note that there is still a fundamental and serious issue with server initiated rendering in conjunction with Spring Webflow 1.0.x. When server initiated rendering thread calls execute and starts the JSF lifecycle, webflow finds the executorKey in the UIViewRoot. However when it comes time to clean up, in the post RenderResponse phase listener, it tries to find the same key in the ExternalContext.requestMap. Aside from not being protected by the above described synchronization because it doesn't enter through the servlet path, the state of the request maps is non-deterministic, resulting in potential deadlocks, or potentially difficult to find race conditions.
        Hide
        Greg Dick added a comment -

        Checked in ViewBoundServer

        Show
        Greg Dick added a comment - Checked in ViewBoundServer
        Hide
        Ted Goddard added a comment -

        Race condition in same block of code has been found in seam-auctionMonitor.

        Show
        Ted Goddard added a comment - Race condition in same block of code has been found in seam-auctionMonitor.

          People

          • Assignee:
            Unassigned
            Reporter:
            Greg Dick
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: