[ 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