Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-70598

Possible race condition in PortletLocalServiceImpl.getPortletId

    Details

      Description

      Description
      If the browser ever sends simultaneous requests to the JVM that require the JVM to look up a struts path, and the _portletIdsByStrutsPath inside of PortletLocalServiceImpl has not been populated yet, then a race condition occurs that results in one of two things happening, depending on the delay between the threads:

      1) Each of the threads detects that _portletIdsByStrutsPath is empty, and tries to populate it simultaneously. This results in all but one of the threads outputting "Duplicate struts path" warning messages to the logs.
      2) One of the threads starts populating _portletIdsByStrutsPath before the other threads check whether or not it is empty. This potentially results in a NullPointerException, and possibly more sinister behavior, because if the first thread has not yet added the struts path to the map that the other threads are trying to look up, then the other threads will all return null and they will not perform the request that the browser asked of them (the consequence of this depends on the portlet).

      Steps to reproduce
      I do not have steps to reproduce in master because I am not aware of any portlets in master that result in multiple struts path requests being fired off simultaneously. If someone knows of a portlet that does this, or can create a custom one that does this, then please let me know and we can update the steps to reproduce accordingly.

      This issue can be tested in ee-7.0.x by taking the following steps:

      1. Use a fresh database and start the server.
      2. Add several categories to the Topic (Global) vocabulary and the Topic (Liferay DXP) vocabulary.
      3. Add an asset publisher to a page on the Liferay DXP site.
      4. Navigate to Control Panel > Configuration > Server Administration and run the following Groovy script:

      com.liferay.portal.kernel.service.PortletLocalServiceUtil.clearCache()
      

      5. Go back to the page with the Asset Publisher, open the asset publisher's configuration, and add a filter by categories.
      6. Click "Select" to choose a category.

      Expected results: No error messages appear in the logs and everything works normally.
      Actual results: Either one of two things happen. Most of the time, you will see a "Duplicate struts path" warning message in the log for every portlet that is deployed (upwards of 200 messages). When this happens, the UI loads normally and everything is fine. However, occasionally, you will instead see the following stack trace in the logs:

      java.lang.NullPointerException
              at com.liferay.portal.kernel.model.PortletInstance._getPortletName(PortletInstance.java:198)
              at com.liferay.portal.kernel.model.PortletInstance.fromPortletInstanceKey(PortletInstance.java:40)
              at com.liferay.portal.kernel.model.PortletConstants.getRootPortletId(PortletConstants.java:170)
              at com.liferay.portal.service.impl.PortletLocalServiceImpl.getPortletById(PortletLocalServiceImpl.java:492)
              at com.liferay.portal.service.impl.PortletLocalServiceImpl.getPortletByStrutsPath(PortletLocalServiceImpl.java:575)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      

      When this happens, one of the Vocabularies will be collapsed, and you have to expand it to see its Categories.

      You can quickly retest this issue by repeating steps 4-6. Just have one tab open in the Groovy console clicking "Execute", and have the other tab on the Asset Publisher's configuration clicking "Select"

      Reproduced in ee-7.0.x (9fb91fcd8afc186172652024997a42fee6fd6787)
      Cannot test in master because we are not aware of any portlets that cause simultaneous requests to be sent to the JVM. If anyone knows of such a portlet or can make a custom one, let me know and we can update the steps to reproduce accordingly. However, from looking at the code, this issue exists in master.

        Attachments

          Activity

            People

            Assignee:
            raven.song Raven Song
            Reporter:
            michael.bowerman Michael Bowerman (Inactive)
            Participants of an Issue:
            Recent user:
            Csaba Turcsan
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:
              Days since last comment:
              3 years, 38 weeks, 2 days ago

                Packages

                Version Package
                7.0.0 DXP SP2
                7.0.0 DXP FP13
                7.0.0 DXP SP3
                7.0.3 CE GA4
                7.1.X
                Master