[ 
https://issues.apache.org/jira/browse/PDFBOX-2815?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Tilman Hausherr updated PDFBOX-2815:
------------------------------------
    Description: 
In COSStream.getDecodeResult(), we have this:
{code}
if (unFilteredStream == null)
{
    doDecode();
}

{code}
{code}
if (unFilteredStream == null || decodeResult == null)
{
   ... throw exception.... (supposedly, decode failed)
}
{code}

The problem is that there is a race condition here. If thread 1 enters this 
method, it sees that unFilteredStream is null, so starts decoding. Before 
actually running the decode, it creates unFilteredStream, then starts decode.

Now, thread 2 enters, sees that unFilteredStream is not null (thread 1 already 
created it), gets to the next if statement, sees that decodeResult is null 
(thread 1 is not finished decode yet), and thinks that the decode failed.

I have solved this on my side by creating:

{code}
private void ensureDecoded()
{
    synchronized (this)
    {
        if (unFilteredStream == null)
        {
            doDecode();
        }
    }
}
{code}

and then replace all 3 instances of this:

{code}
if (unFilteredStream == null)
{
    doDecode();
}
{code}

with this:

{code}
ensureDecoded();
{code}

  was:
In COSStream.getDecodeResult(), we have this:

if (unFilteredStream == null)
{
    doDecode();
}

if (unFilteredStream == null || decodeResult == null)
{
   ... throw exception.... (supposedly, decode failed)
}

The problem is that there is a race condition here. If thread 1 enters this 
method, it sees that unFilteredStream is null, so starts decoding. Before 
actually running the decode, it creates unFilteredStream, then starts decode.

Now, thread 2 enters, sees that unFilteredStream is not null (thread 1 already 
created it), gets to the next if statement, sees that decodeResult is null 
(thread 1 is not finished decode yet), and thinks that the decode failed.

I have solved this on my side by creating:

private void ensureDecoded()
{
    synchronized (this)
    {
        if (unFilteredStream == null)
        {
            doDecode();
        }
    }
}

and then replace all 3 instances of this:

if (unFilteredStream == null)
{
    doDecode();
}

with this:

ensureDecoded();


> Race conditions in COSStream decoding
> -------------------------------------
>
>                 Key: PDFBOX-2815
>                 URL: https://issues.apache.org/jira/browse/PDFBOX-2815
>             Project: PDFBox
>          Issue Type: Bug
>          Components: PDModel
>    Affects Versions: 2.0.0
>         Environment: Slow filter decoders
>            Reporter: Jesse Long
>            Priority: Minor
>
> In COSStream.getDecodeResult(), we have this:
> {code}
> if (unFilteredStream == null)
> {
>     doDecode();
> }
> {code}
> {code}
> if (unFilteredStream == null || decodeResult == null)
> {
>    ... throw exception.... (supposedly, decode failed)
> }
> {code}
> The problem is that there is a race condition here. If thread 1 enters this 
> method, it sees that unFilteredStream is null, so starts decoding. Before 
> actually running the decode, it creates unFilteredStream, then starts decode.
> Now, thread 2 enters, sees that unFilteredStream is not null (thread 1 
> already created it), gets to the next if statement, sees that decodeResult is 
> null (thread 1 is not finished decode yet), and thinks that the decode failed.
> I have solved this on my side by creating:
> {code}
> private void ensureDecoded()
> {
>     synchronized (this)
>     {
>         if (unFilteredStream == null)
>         {
>             doDecode();
>         }
>     }
> }
> {code}
> and then replace all 3 instances of this:
> {code}
> if (unFilteredStream == null)
> {
>     doDecode();
> }
> {code}
> with this:
> {code}
> ensureDecoded();
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to