You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by bu...@apache.org on 2003/07/01 15:28:36 UTC

DO NOT REPLY [Bug 21224] New: - race condition in LookupDispatchAction.execute

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=21224>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=21224

race condition in LookupDispatchAction.execute

           Summary: race condition in LookupDispatchAction.execute
           Product: Struts
           Version: Nightly Build
          Platform: All
        OS/Version: Other
            Status: NEW
          Severity: Normal
          Priority: Other
         Component: Standard Actions
        AssignedTo: struts-dev@jakarta.apache.org
        ReportedBy: skubibugs@skubi.eu.org


This bug is in version 1.1 release.

I found it by reading source code. I did not reproduce it, because
it is a race condition, potentially very hard to reproduce.

The race condition may occur if

  - two HTTP requests are serviced concurrently
  - both requests use the same locale
  - both requests use an action based on LookupDispatchAction
  - LookupDispatchAction.localeMap does not contain yet a map for the locale
    in question

The race condition should have the following effect: one of the HTTP requests
will use an empty map for the reverse-mapping of the submit button value into
a message key.

To understand this, consider a concurrent execution on behalf of two
HTTP requests of the following code. Assume that both requests use the same
locale, and that LookupDispatchAction.localeMap does not contain yet a map
for this locale:

In method execute in LookupDispatchAction:

206 synchronized (localeMap) {
207     lookupMap = (Map) this.localeMap.get(userLocale);
208     if (lookupMap == null) {
209         newLookupMap = true;
210         lookupMap = new HashMap();
211         this.localeMap.put(userLocale, lookupMap);
212     }
213 }

- this critical section was first executed by HTTP request 1. This request
found lookupMap == null, and therefore set newLookupMap = true, and inserted
a new, empty HashMap into localeMap.

- then, the critical section was executed by HTTP request 2. Because request
1 inserted an object into localeMap, at key userLocal, request 2 found
lookupMap != null. As a result, for request 2 we have newLookupMap = false.

The code continues as follows:

214         
215 synchronized (lookupMap) {
216     if (newLookupMap) {

         <<< Here, we insert content into lookupMap >>>

245 }

This critical section is first executed by request 2. lookupMap
receives no content, because newLookupMap is empty. At this point,
request 2 is ready to use an empty lookup map, and fail to dispatch the
request to the relevant method. Voila, the race condition occured.

---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org