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

Gonçalo Rodrigues updated CXF-4356:
-----------------------------------

    Description: 
I’m implementing a web service to upload files (from 120 Kb to 1 Mb). Most of 
the time everything works fine, but sometimes (randomly) the uploaded file is 
empty (size == 0) in the target platform. 

After some debugging I found that the problem comes from the temp file created 
by the {{CachedOutputStream}} that is deleted during the process of getting the 
cached stream. In fact, {{maybeDeleteTempFile}} is called before 
{{getInputStream}} which returns an empty {{LoadingByteArrayOutputStream}}. The 
{{finalize}} method of {{FileInputStream}} calls its {{close}} method which is 
overridden in {{CachedOutputStream#getInputStream}} to delete the temp file.

I tried to synchronize all the methods dealing with {{tempFile}} but it didn’t 
resolve my problem.

The stack: 

{code}
Daemon System Thread [Finalizer] (Suspended (breakpoint at line 490 in 
CachedOutputStream))     
        CachedOutputStream.maybeDeleteTempFile(Object) line: 490        
        CachedOutputStream.access$000(CachedOutputStream, Object) line: 43      
        CachedOutputStream$1.close() line: 469  
        CachedOutputStream$1(FileInputStream).finalize() line: 381      
        Finalizer.invokeFinalizeMethod(Object) line: not available [native 
method]      
        Finalizer.runFinalizer() line: 83       
        Finalizer.access$100(Finalizer) line: 14        
        Finalizer$FinalizerThread.run() line: 160       
{code} 

The {{getInputStream}} method: 

{code:java}
public InputStream getInputStream() throws IOException {
        flush();
        if (inmem) {
                if (currentStream instanceof LoadingByteArrayOutputStream) {
                        return ((LoadingByteArrayOutputStream) 
currentStream).createInputStream();
                } else if (currentStream instanceof ByteArrayOutputStream) {
                        return new 
ByteArrayInputStream(((ByteArrayOutputStream) currentStream).toByteArray());
                } else if (currentStream instanceof PipedOutputStream) {
                        return new PipedInputStream((PipedOutputStream) 
currentStream);
                } else {
                        return null;
                }
        } else {
                try {
                        FileInputStream fileInputStream = new 
FileInputStream(tempFile) {
                                public void close() throws IOException {
                                        super.close();
                                        maybeDeleteTempFile(this);
                                }
                        };
                        streamList.add(fileInputStream);
                        return fileInputStream;
                } catch (FileNotFoundException e) {
                        throw new IOException("Cached file was deleted, " + 
e.toString());
                }
        }
}
{code} 


The {{maybeDeleteTempFile}} method: 

{code:java}
private void maybeDeleteTempFile(Object stream) {
        streamList.remove(stream);
        if (!inmem && tempFile != null && streamList.isEmpty() && 
allowDeleteOfFile) {
                if (currentStream != null) {
                        try {
                                currentStream.close();
                                postClose();
                        } catch (Exception e) {
                                //ignore
                        }
                }
                tempFile.delete();
                tempFile = null;
                currentStream = new LoadingByteArrayOutputStream(1024);
                inmem = true;
        }
}
{code} 

  was:
Sometimes (randomly) the temp file is deleted during the process of getting the 
cached stream. In fact, {{maybeDeleteTempFile}} is called before 
{{getInputStream}} which returns an empty {{LoadingByteArrayOutputStream}}. The 
{{finalize}} method of {{FileInputStream}} calls its {{close}} method which is 
overridden in {{CachedOutputStream#getInputStream}} to delete the temp file.

I tried to synchronize all the methods dealing with {{tempFile}} but it didn’t 
resolve my problem.

The stack: 

{code}
Daemon System Thread [Finalizer] (Suspended (breakpoint at line 490 in 
CachedOutputStream))     
        CachedOutputStream.maybeDeleteTempFile(Object) line: 490        
        CachedOutputStream.access$000(CachedOutputStream, Object) line: 43      
        CachedOutputStream$1.close() line: 469  
        CachedOutputStream$1(FileInputStream).finalize() line: 381      
        Finalizer.invokeFinalizeMethod(Object) line: not available [native 
method]      
        Finalizer.runFinalizer() line: 83       
        Finalizer.access$100(Finalizer) line: 14        
        Finalizer$FinalizerThread.run() line: 160       
{code} 

The {{getInputStream}} method: 

{code:java}
public InputStream getInputStream() throws IOException {
        flush();
        if (inmem) {
                if (currentStream instanceof LoadingByteArrayOutputStream) {
                        return ((LoadingByteArrayOutputStream) 
currentStream).createInputStream();
                } else if (currentStream instanceof ByteArrayOutputStream) {
                        return new 
ByteArrayInputStream(((ByteArrayOutputStream) currentStream).toByteArray());
                } else if (currentStream instanceof PipedOutputStream) {
                        return new PipedInputStream((PipedOutputStream) 
currentStream);
                } else {
                        return null;
                }
        } else {
                try {
                        FileInputStream fileInputStream = new 
FileInputStream(tempFile) {
                                public void close() throws IOException {
                                        super.close();
                                        maybeDeleteTempFile(this);
                                }
                        };
                        streamList.add(fileInputStream);
                        return fileInputStream;
                } catch (FileNotFoundException e) {
                        throw new IOException("Cached file was deleted, " + 
e.toString());
                }
        }
}
{code} 


The {{maybeDeleteTempFile}} method: 

{code:java}
private void maybeDeleteTempFile(Object stream) {
        streamList.remove(stream);
        if (!inmem && tempFile != null && streamList.isEmpty() && 
allowDeleteOfFile) {
                if (currentStream != null) {
                        try {
                                currentStream.close();
                                postClose();
                        } catch (Exception e) {
                                //ignore
                        }
                }
                tempFile.delete();
                tempFile = null;
                currentStream = new LoadingByteArrayOutputStream(1024);
                inmem = true;
        }
}
{code} 

    
> Temp file deleted before returning the stream in CachedOutputStream
> -------------------------------------------------------------------
>
>                 Key: CXF-4356
>                 URL: https://issues.apache.org/jira/browse/CXF-4356
>             Project: CXF
>          Issue Type: Bug
>    Affects Versions: 2.5
>            Reporter: Gonçalo Rodrigues
>
> I’m implementing a web service to upload files (from 120 Kb to 1 Mb). Most of 
> the time everything works fine, but sometimes (randomly) the uploaded file is 
> empty (size == 0) in the target platform. 
> After some debugging I found that the problem comes from the temp file 
> created by the {{CachedOutputStream}} that is deleted during the process of 
> getting the cached stream. In fact, {{maybeDeleteTempFile}} is called before 
> {{getInputStream}} which returns an empty {{LoadingByteArrayOutputStream}}. 
> The {{finalize}} method of {{FileInputStream}} calls its {{close}} method 
> which is overridden in {{CachedOutputStream#getInputStream}} to delete the 
> temp file.
> I tried to synchronize all the methods dealing with {{tempFile}} but it 
> didn’t resolve my problem.
> The stack: 
> {code}
> Daemon System Thread [Finalizer] (Suspended (breakpoint at line 490 in 
> CachedOutputStream))   
>       CachedOutputStream.maybeDeleteTempFile(Object) line: 490        
>       CachedOutputStream.access$000(CachedOutputStream, Object) line: 43      
>       CachedOutputStream$1.close() line: 469  
>       CachedOutputStream$1(FileInputStream).finalize() line: 381      
>       Finalizer.invokeFinalizeMethod(Object) line: not available [native 
> method]      
>       Finalizer.runFinalizer() line: 83       
>       Finalizer.access$100(Finalizer) line: 14        
>       Finalizer$FinalizerThread.run() line: 160       
> {code} 
> The {{getInputStream}} method: 
> {code:java}
> public InputStream getInputStream() throws IOException {
>       flush();
>       if (inmem) {
>               if (currentStream instanceof LoadingByteArrayOutputStream) {
>                       return ((LoadingByteArrayOutputStream) 
> currentStream).createInputStream();
>               } else if (currentStream instanceof ByteArrayOutputStream) {
>                       return new 
> ByteArrayInputStream(((ByteArrayOutputStream) currentStream).toByteArray());
>               } else if (currentStream instanceof PipedOutputStream) {
>                       return new PipedInputStream((PipedOutputStream) 
> currentStream);
>               } else {
>                       return null;
>               }
>       } else {
>               try {
>                       FileInputStream fileInputStream = new 
> FileInputStream(tempFile) {
>                               public void close() throws IOException {
>                                       super.close();
>                                       maybeDeleteTempFile(this);
>                               }
>                       };
>                       streamList.add(fileInputStream);
>                       return fileInputStream;
>               } catch (FileNotFoundException e) {
>                       throw new IOException("Cached file was deleted, " + 
> e.toString());
>               }
>       }
> }
> {code} 
> The {{maybeDeleteTempFile}} method: 
> {code:java}
> private void maybeDeleteTempFile(Object stream) {
>       streamList.remove(stream);
>       if (!inmem && tempFile != null && streamList.isEmpty() && 
> allowDeleteOfFile) {
>               if (currentStream != null) {
>                       try {
>                               currentStream.close();
>                               postClose();
>                       } catch (Exception e) {
>                               //ignore
>                       }
>               }
>               tempFile.delete();
>               tempFile = null;
>               currentStream = new LoadingByteArrayOutputStream(1024);
>               inmem = true;
>       }
> }
> {code} 

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira


Reply via email to