FULL PRODUCT VERSION :
java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux X 2.6.5-7.319-smp #1 SMP Mon Aug 24 10:05:14 UTC 2009 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
If an I/O error, e.g. disk full,, occurs during close on a BufferedOutputStream, the error will go unnoticed.
close does attempt to flush the buffer, but it swallows an error and then closes the underlying stream.
It should probably still try to close the underlying stream, but exception from flush
should be re-thrown.
Few, if any, programs call flush on streams to close them.
Usually a program will report and error if th disk becomes full, but if will not tell the user that a file might have been corrupted before the point of error.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Extract the following two files on a Linux machine and run the shell
script.
==BEGIN Fill.java
#!/bin/sh -e
# Linux script requiring.User may want to change mount point and/or loop device
here=$(pwd)
export CLASSPATH=$(pwd)
MOUNTPOINT=/mnt/almostfull
DEVICE=/dev/loop0
umount $MOUNTPOINT || true
/sbin/losetup -d $DEVICE || true
dd if=/dev/zero of=mydevice.dsk bs=512 count=1024
/sbin/losetup $DEVICE mydevice.dsk
/sbin/mkfs.ext2 $DEVICE
mkdir -p $MOUNTPOINT
mount $DEVICE $MOUNTPOINT
javac Fill.java
pushd $MOUNTPOINT
touch empty
if dd if=/dev/zero of=filler.dat bs=1
then
: We fill the disk, so it becomes full
echo internal error
exit 1
fi
rm empty
if java Fill -fail
then
: # explicit flush, should fail
echo internal error
exit 1
fi
java Fill
echo Should not get here. Program failed to write file
popd
set +e
umount $MOUNTPOINT || true
/sbin/losetup -d $DEVICE || true
END demo.sh
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
sudo bash -x -e ./x.sh
++ pwd
+ here=/home/roro/tmp
++ pwd
+ export CLASSPATH=/home/roro/tmp
+ CLASSPATH=/home/roro/tmp
+ MOUNTPOINT=/mnt/almostfull
+ DEVICE=/dev/loop0
+ umount /mnt/almostfull
umount: /mnt/almostfull: not mounted
+ true
+ /sbin/losetup -d /dev/loop0
ioctl: LOOP_CLR_FD: No such device or address
+ true
+ dd if=/dev/zero of=mydevice.dsk bs=512 count=1024
1024+0 records in
1024+0 records out
+ /sbin/losetup /dev/loop0 mydevice.dsk
+ /sbin/mkfs.ext2 /dev/loop0
mke2fs 1.38 (30-Jun-2005)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
64 inodes, 512 blocks
25 blocks (4.88%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
64 inodes per group
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 32 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
+ mkdir -p /mnt/almostfull
+ mount /dev/loop0 /mnt/almostfull
+ javac Fill.java
+ pushd /mnt/almostfull
/mnt/almostfull ~/tmp
+ touch empty
+ dd if=/dev/zero of=filler.dat bs=1
dd: writing `filler.dat': No space left on device
494593+0 records in
494592+0 records out
+ rm empty
+ java Fill -fail
Exception in thread "main" java.io.IOException: No space left on device
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:282)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at Fill.main(Fill.java:8)
+ java Fill
Exception in thread "main" java.io.IOException: No space left on device
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:282)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at Fill.main(Fill.java:8)
# i.e. both invocations of Fill should fail
ACTUAL -
sudo bash -x -e ./x.sh
++ pwd
+ here=/home/roro/tmp
++ pwd
+ export CLASSPATH=/home/roro/tmp
+ CLASSPATH=/home/roro/tmp
+ MOUNTPOINT=/mnt/almostfull
+ DEVICE=/dev/loop0
+ umount /mnt/almostfull
umount: /mnt/almostfull: not mounted
+ true
+ /sbin/losetup -d /dev/loop0
ioctl: LOOP_CLR_FD: No such device or address
+ true
+ dd if=/dev/zero of=mydevice.dsk bs=512 count=1024
1024+0 records in
1024+0 records out
+ /sbin/losetup /dev/loop0 mydevice.dsk
+ /sbin/mkfs.ext2 /dev/loop0
mke2fs 1.38 (30-Jun-2005)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
64 inodes, 512 blocks
25 blocks (4.88%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
64 inodes per group
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 32 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
+ mkdir -p /mnt/almostfull
+ mount /dev/loop0 /mnt/almostfull
+ javac Fill.java
+ pushd /mnt/almostfull
/mnt/almostfull ~/tmp
+ touch empty
+ dd if=/dev/zero of=filler.dat bs=1
dd: writing `filler.dat': No space left on device
494593+0 records in
494592+0 records out
+ rm empty
+ java Fill -fail
Exception in thread "main" java.io.IOException: No space left on device
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:282)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at Fill.main(Fill.java:8)
+ java Fill
+ echo Should not get here. Program failed to write file
Should not get here. Program failed to write file
+ popd
~/tmp
+ set +e
+ umount /mnt/almostfull
+ /sbin/losetup -d /dev/loop0
# i.e. the program that only uses close() does not report an error
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.*;
public class Fill {
public static void main(String[] args) throws IOException {
BufferedOutputStream b = new BufferedOutputStream(new FileOutputStream("full"));
b.write("data".getBytes());
if (args.length > 0)
b.flush();
b.close();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
alway call flush before close
java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux X 2.6.5-7.319-smp #1 SMP Mon Aug 24 10:05:14 UTC 2009 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
If an I/O error, e.g. disk full,, occurs during close on a BufferedOutputStream, the error will go unnoticed.
close does attempt to flush the buffer, but it swallows an error and then closes the underlying stream.
It should probably still try to close the underlying stream, but exception from flush
should be re-thrown.
Few, if any, programs call flush on streams to close them.
Usually a program will report and error if th disk becomes full, but if will not tell the user that a file might have been corrupted before the point of error.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Extract the following two files on a Linux machine and run the shell
script.
==BEGIN Fill.java
#!/bin/sh -e
# Linux script requiring.User may want to change mount point and/or loop device
here=$(pwd)
export CLASSPATH=$(pwd)
MOUNTPOINT=/mnt/almostfull
DEVICE=/dev/loop0
umount $MOUNTPOINT || true
/sbin/losetup -d $DEVICE || true
dd if=/dev/zero of=mydevice.dsk bs=512 count=1024
/sbin/losetup $DEVICE mydevice.dsk
/sbin/mkfs.ext2 $DEVICE
mkdir -p $MOUNTPOINT
mount $DEVICE $MOUNTPOINT
javac Fill.java
pushd $MOUNTPOINT
touch empty
if dd if=/dev/zero of=filler.dat bs=1
then
: We fill the disk, so it becomes full
echo internal error
exit 1
fi
rm empty
if java Fill -fail
then
: # explicit flush, should fail
echo internal error
exit 1
fi
java Fill
echo Should not get here. Program failed to write file
popd
set +e
umount $MOUNTPOINT || true
/sbin/losetup -d $DEVICE || true
END demo.sh
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
sudo bash -x -e ./x.sh
++ pwd
+ here=/home/roro/tmp
++ pwd
+ export CLASSPATH=/home/roro/tmp
+ CLASSPATH=/home/roro/tmp
+ MOUNTPOINT=/mnt/almostfull
+ DEVICE=/dev/loop0
+ umount /mnt/almostfull
umount: /mnt/almostfull: not mounted
+ true
+ /sbin/losetup -d /dev/loop0
ioctl: LOOP_CLR_FD: No such device or address
+ true
+ dd if=/dev/zero of=mydevice.dsk bs=512 count=1024
1024+0 records in
1024+0 records out
+ /sbin/losetup /dev/loop0 mydevice.dsk
+ /sbin/mkfs.ext2 /dev/loop0
mke2fs 1.38 (30-Jun-2005)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
64 inodes, 512 blocks
25 blocks (4.88%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
64 inodes per group
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 32 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
+ mkdir -p /mnt/almostfull
+ mount /dev/loop0 /mnt/almostfull
+ javac Fill.java
+ pushd /mnt/almostfull
/mnt/almostfull ~/tmp
+ touch empty
+ dd if=/dev/zero of=filler.dat bs=1
dd: writing `filler.dat': No space left on device
494593+0 records in
494592+0 records out
+ rm empty
+ java Fill -fail
Exception in thread "main" java.io.IOException: No space left on device
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:282)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at Fill.main(Fill.java:8)
+ java Fill
Exception in thread "main" java.io.IOException: No space left on device
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:282)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at Fill.main(Fill.java:8)
# i.e. both invocations of Fill should fail
ACTUAL -
sudo bash -x -e ./x.sh
++ pwd
+ here=/home/roro/tmp
++ pwd
+ export CLASSPATH=/home/roro/tmp
+ CLASSPATH=/home/roro/tmp
+ MOUNTPOINT=/mnt/almostfull
+ DEVICE=/dev/loop0
+ umount /mnt/almostfull
umount: /mnt/almostfull: not mounted
+ true
+ /sbin/losetup -d /dev/loop0
ioctl: LOOP_CLR_FD: No such device or address
+ true
+ dd if=/dev/zero of=mydevice.dsk bs=512 count=1024
1024+0 records in
1024+0 records out
+ /sbin/losetup /dev/loop0 mydevice.dsk
+ /sbin/mkfs.ext2 /dev/loop0
mke2fs 1.38 (30-Jun-2005)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
64 inodes, 512 blocks
25 blocks (4.88%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
64 inodes per group
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 32 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
+ mkdir -p /mnt/almostfull
+ mount /dev/loop0 /mnt/almostfull
+ javac Fill.java
+ pushd /mnt/almostfull
/mnt/almostfull ~/tmp
+ touch empty
+ dd if=/dev/zero of=filler.dat bs=1
dd: writing `filler.dat': No space left on device
494593+0 records in
494592+0 records out
+ rm empty
+ java Fill -fail
Exception in thread "main" java.io.IOException: No space left on device
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:282)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at Fill.main(Fill.java:8)
+ java Fill
+ echo Should not get here. Program failed to write file
Should not get here. Program failed to write file
+ popd
~/tmp
+ set +e
+ umount /mnt/almostfull
+ /sbin/losetup -d /dev/loop0
# i.e. the program that only uses close() does not report an error
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.*;
public class Fill {
public static void main(String[] args) throws IOException {
BufferedOutputStream b = new BufferedOutputStream(new FileOutputStream("full"));
b.write("data".getBytes());
if (args.length > 0)
b.flush();
b.close();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
alway call flush before close
- duplicates
-
JDK-7015589 (spec) BufferedWriter.close leaves stream open if close of underlying Writer fails
-
- Closed
-