cxf-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Daniel Kulp (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (CXF-4356) Temp file deleted before returning the stream in CachedOutputStream
Date Tue, 17 Jul 2012 03:06:35 GMT

    [ https://issues.apache.org/jira/browse/CXF-4356?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13415858#comment-13415858
] 

Daniel Kulp commented on CXF-4356:
----------------------------------

I believe a simple patch of:

{code}
--- a/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java
+++ b/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java
@@ -464,9 +464,13 @@ public class CachedOutputStream extends OutputStream {
         } else {
             try {
                 FileInputStream fileInputStream = new FileInputStream(tempFile) {
+                    boolean closed;
                     public void close() throws IOException {
-                        super.close();
-                        maybeDeleteTempFile(this);
+                        if (!closed) {
+                            super.close();
+                            maybeDeleteTempFile(this);
+                        }
+                        closed = true;
                     }
                 };
                 streamList.add(fileInputStream);
{code}

will fix this.  I need to test this more though.  

Apparently, the FileInputStream.finalize method calls close a second time which, if not guarded
as above, could cause the maybeDeleteTempFile to be called again and delete the file prematurely.
                
> 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, 2.6
>            Reporter: Gonçalo Rodrigues
>            Assignee: Daniel Kulp
>         Attachments: cxf-4356-reproducer.zip
>
>
> 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

       

Mime
View raw message