Return-Path: X-Original-To: apmail-commons-issues-archive@minotaur.apache.org Delivered-To: apmail-commons-issues-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 5D021189CF for ; Fri, 22 Jan 2016 01:22:40 +0000 (UTC) Received: (qmail 69862 invoked by uid 500); 22 Jan 2016 01:22:40 -0000 Delivered-To: apmail-commons-issues-archive@commons.apache.org Received: (qmail 69731 invoked by uid 500); 22 Jan 2016 01:22:40 -0000 Mailing-List: contact issues-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: issues@commons.apache.org Delivered-To: mailing list issues@commons.apache.org Received: (qmail 69698 invoked by uid 99); 22 Jan 2016 01:22:40 -0000 Received: from arcas.apache.org (HELO arcas) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 22 Jan 2016 01:22:40 +0000 Received: from arcas.apache.org (localhost [127.0.0.1]) by arcas (Postfix) with ESMTP id E421C2C14F2 for ; Fri, 22 Jan 2016 01:22:39 +0000 (UTC) Date: Fri, 22 Jan 2016 01:22:39 +0000 (UTC) From: "Nicholas Byrd (JIRA)" To: issues@commons.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Updated] (IO-497) DeferredFileOutputStream produces unhandled IOExceptions if the java.io.tmpdir is deleted MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ https://issues.apache.org/jira/browse/IO-497?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Nicholas Byrd updated IO-497: ----------------------------- Attachment: dfos-bug.tar.gz Attached you will find the small Maven project that highlights this bug. Please see the "TestDeferredFileOutputStream.java" file. The tarball contains a README file documenting how to run the tests from the command line. Alternatively, if you would like the file by itself, I will paste it here: {code:Java} import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.DeferredFileOutputStream; import org.junit.Before; import org.junit.Test; import java.io.*; import java.util.Random; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; /** * Tests the Commons IO {@link org.apache.commons.io.output.DeferredFileOutputStream}. */ public class TestDeferredFileOutputStream { /** * The threshold value that will be used to construct * {@link org.apache.commons.io.output.DeferredFileOutputStream}s. 10KiB was chosen because * this value is used in the Commons FileUpload library. */ public static final int THRESHOLD = 10240; /** * Will hold a sizable chunk of data that the test can pass through streams. */ private byte[] data; /** * Sets up the test fixture, creating some data to work with and ensuring that * the tmpdir is usable. */ @Before public void setup() { // Create a (fairly large) chunk of data for the test to work with. // Must be larger than the stream's threshold, so that // org.apache.commons.io.output.ThresholdingOutputStream.thresholdReached() is invoked. data = new byte[2*THRESHOLD]; Random rng = new Random(System.currentTimeMillis()); rng.nextBytes(data); // ensure that the java tmpdir exists between tests File tmpDir = new File(System.getProperty("java.io.tmpdir")); if (!tmpDir.isDirectory()) { assumeFalse("tmpDir exists but is actually a file", tmpDir.exists()); assumeTrue("able to rebuild tmpdir", tmpDir.mkdir()); } assumeTrue("can write to tmpDir", tmpDir.canWrite()); assumeTrue("can read from tmpDir", tmpDir.canRead()); } /** * This is a basic test of the DeferredFileOutputStream. This is not expected to fail. * @throws IOException in the event that something goes horribly wrong. */ @Test public void testStream() throws IOException { File someFile = File.createTempFile("something", "tmp"); try (InputStream is = new ByteArrayInputStream(data)) { try (OutputStream dfos = new DeferredFileOutputStream(THRESHOLD, someFile)) { IOUtils.copy(is, dfos); } } } // This test fails due to an uncaught FileNotFoundException that bubbles // up from DeferredFileOutputStream. /** * Tests what happens if the tmpDir gets deleted before the DeferredFileOutputStream tries to use it. */ @Test public void testStreamWithDelete() throws IOException { File someFile = File.createTempFile("something2", ".tmp"); File tmpDir = new File(System.getProperty("java.io.tmpdir")); FileUtils.deleteDirectory(tmpDir); try (InputStream is = new ByteArrayInputStream(data)) { try (OutputStream dfos = new DeferredFileOutputStream(THRESHOLD, someFile)) { IOUtils.copy(is, dfos); } } } // This test fails due to an uncaught IOException bubbling up from DeferredFileOutputStream. /** * Tests what happens if the tmpDir is not usable due to being deleted. Uses * the non-{@link java.io.File} constructor when creating the * {@link org.apache.commons.io.output.DeferredFileOutputStream}. */ @Test public void testStreamWithDeleteAlternative() throws IOException { File tmpDir = new File(System.getProperty("java.io.tmpdir")); FileUtils.deleteDirectory(tmpDir); try (InputStream is = new ByteArrayInputStream(data)) { try (OutputStream dfos = new DeferredFileOutputStream(THRESHOLD, "something3", ".tmp", tmpDir)) { IOUtils.copy(is, dfos); } } } } {code} > DeferredFileOutputStream produces unhandled IOExceptions if the java.io.tmpdir is deleted > ----------------------------------------------------------------------------------------- > > Key: IO-497 > URL: https://issues.apache.org/jira/browse/IO-497 > Project: Commons IO > Issue Type: Bug > Components: Streams/Writers > Affects Versions: 2.4 > Environment: unix-like operating systems where temporary disk storage is routinely purged; CentOS specifically > Reporter: Nicholas Byrd > Attachments: dfos-bug.tar.gz > > > In the event that the Java temporary directory is deleted prior to the DeferredFileOutputStream trying to use it, the stream will throw one of two different IOExceptions (depending on how the Stream was constructed). > This may sound like an unrealistic use-case at first, but it is legitimate as one of my company's applications encountered it after the underlying operating system (CentOS) automatically purged the contents of its tmp directory. (The application uses Commons FileUpload, which invokes DeferredFileOutputStream and does not handle the error itself.) Our current work-around is to restart the server when this happens, but we feel that the underlying library should perhaps be intelligent enough to recover from such an error. > Additionally, it seems an awkward experience that two different errors are produced based on how the stream was constructed. One approach produces a FileNotFoundException while the other produces a plain IOException. > A small maven project containing a single JUnit test that highlights the error will be attached. -- This message was sent by Atlassian JIRA (v6.3.4#6332)