Duplicate :
|
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