Uploaded image for project: 'XWiki Commons'
  1. XWiki Commons
  2. XCOMMONS-3752

Job status REST endpoint can fail with a NullPointerException while the job is running

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • Major
    • 18.4.5, 17.10.13, 18.8.0-rc-1
    • 17.10.12
    • Job
    • None
    • Unit
    • Unknown
    • N/A
    • N/A

    Description

      Problem

      GET /rest/jobstatus/<id> can return an HTTP 500 with a NullPointerException while the job it reports on is still running:

      java.lang.NullPointerException: Cannot invoke "org.xwiki.job.internal.DefaultJobProgressStep.getOffset()" because the return value of "org.xwiki.job.internal.DefaultJobProgressStep.getParent()" is null
      	at org.xwiki.job.internal.DefaultJobProgress.getCurrentLevelOffset(DefaultJobProgress.java:250)
      	at org.xwiki.rest.internal.ModelFactory.toRestJobProgress(ModelFactory.java:1251)
      	at org.xwiki.rest.internal.ModelFactory.toRestJobStatus(ModelFactory.java:1218)
      	at org.xwiki.rest.internal.resources.job.JobStatusResourceImpl.getJobStatus(JobStatusResourceImpl.java:47)
      

      Any UI that polls job status while the job progresses can hit this, and the progress bar it feeds then breaks. It was observed in App Within Minutes: adding an application entry polls /rest/jobstatus/refactoring/create/..., that poll returned 500, the page never reloaded and the operation appeared to hang.

      Cause

      DefaultJobProgress#getCurrentLevelOffset() evaluates getCurrentStep() twice:

      return getCurrentStep().getParent() != null ? getCurrentStep().getParent().getOffset() : getOffset();
      

      currentStep is a plain, non-volatile field that the job thread reassigns as the job progresses, while the REST thread reads it. Between the null check and the dereference the job thread can advance the progress so that the second getCurrentStep() returns the root step, whose parent is null — the NPE therefore happens on the very line meant to guard against it.

      The null check was added by XCOMMONS-1167 (9.1), and the double read has been there ever since, so every version from 9.1 onwards is affected. Being a race, it reproduces rarely.

      Fix

      Read the parent once:

      DefaultJobProgressStep parent = getCurrentStep().getParent();
      return parent != null ? parent.getOffset() : getOffset();
      

      Occurrence

      Seen on CI in XWiki Environment Tests / xwiki-platform / stable-18.4.x #113, where it made two App Within Minutes functional tests time out: LiveTableGeneratorIT.titleField and AppsLiveTableIT.testEditApplication.

      Attachments

        Activity

          People

            vmassol Vincent Massol
            vmassol Vincent Massol
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: