@@ -593,13 +593,43 @@ def test_unbounded_file(self):
593
593
with self .open (zero , "r" ) as f :
594
594
self .assertRaises (OverflowError , f .read )
595
595
596
- def test_flush_error_on_close (self ):
597
- f = self .open (support .TESTFN , "wb" , buffering = 0 )
596
+ def check_flush_error_on_close (self , * args , ** kwargs ):
597
+ # Test that the file is closed despite failed flush
598
+ # and that flush() is called before file closed.
599
+ f = self .open (* args , ** kwargs )
600
+ closed = []
598
601
def bad_flush ():
602
+ closed [:] = [f .closed ]
599
603
raise OSError ()
600
604
f .flush = bad_flush
601
605
self .assertRaises (OSError , f .close ) # exception not swallowed
602
606
self .assertTrue (f .closed )
607
+ self .assertTrue (closed ) # flush() called
608
+ self .assertFalse (closed [0 ]) # flush() called before file closed
609
+
610
+ def test_flush_error_on_close (self ):
611
+ # raw file
612
+ # Issue #5700: io.FileIO calls flush() after file closed
613
+ self .check_flush_error_on_close (support .TESTFN , 'wb' , buffering = 0 )
614
+ fd = os .open (support .TESTFN , os .O_WRONLY | os .O_CREAT )
615
+ self .check_flush_error_on_close (fd , 'wb' , buffering = 0 )
616
+ fd = os .open (support .TESTFN , os .O_WRONLY | os .O_CREAT )
617
+ self .check_flush_error_on_close (fd , 'wb' , buffering = 0 , closefd = False )
618
+ os .close (fd )
619
+ # buffered io
620
+ self .check_flush_error_on_close (support .TESTFN , 'wb' )
621
+ fd = os .open (support .TESTFN , os .O_WRONLY | os .O_CREAT )
622
+ self .check_flush_error_on_close (fd , 'wb' )
623
+ fd = os .open (support .TESTFN , os .O_WRONLY | os .O_CREAT )
624
+ self .check_flush_error_on_close (fd , 'wb' , closefd = False )
625
+ os .close (fd )
626
+ # text io
627
+ self .check_flush_error_on_close (support .TESTFN , 'w' )
628
+ fd = os .open (support .TESTFN , os .O_WRONLY | os .O_CREAT )
629
+ self .check_flush_error_on_close (fd , 'w' )
630
+ fd = os .open (support .TESTFN , os .O_WRONLY | os .O_CREAT )
631
+ self .check_flush_error_on_close (fd , 'w' , closefd = False )
632
+ os .close (fd )
603
633
604
634
def test_multi_close (self ):
605
635
f = self .open (support .TESTFN , "wb" , buffering = 0 )
@@ -788,13 +818,21 @@ def test_repr(self):
788
818
self .assertEqual (repr (b ), "<%s name=b'dummy'>" % clsname )
789
819
790
820
def test_flush_error_on_close (self ):
821
+ # Test that buffered file is closed despite failed flush
822
+ # and that flush() is called before file closed.
791
823
raw = self .MockRawIO ()
824
+ closed = []
792
825
def bad_flush ():
826
+ closed [:] = [b .closed , raw .closed ]
793
827
raise OSError ()
794
828
raw .flush = bad_flush
795
829
b = self .tp (raw )
796
830
self .assertRaises (OSError , b .close ) # exception not swallowed
797
831
self .assertTrue (b .closed )
832
+ self .assertTrue (raw .closed )
833
+ self .assertTrue (closed ) # flush() called
834
+ self .assertFalse (closed [0 ]) # flush() called before file closed
835
+ self .assertFalse (closed [1 ])
798
836
799
837
def test_close_error_on_close (self ):
800
838
raw = self .MockRawIO ()
@@ -2618,12 +2656,20 @@ def run(n):
2618
2656
self .assertEqual (content .count ("Thread%03d\n " % n ), 1 )
2619
2657
2620
2658
def test_flush_error_on_close (self ):
2659
+ # Test that text file is closed despite failed flush
2660
+ # and that flush() is called before file closed.
2621
2661
txt = self .TextIOWrapper (self .BytesIO (self .testdata ), encoding = "ascii" )
2662
+ closed = []
2622
2663
def bad_flush ():
2664
+ closed [:] = [txt .closed , txt .buffer .closed ]
2623
2665
raise OSError ()
2624
2666
txt .flush = bad_flush
2625
2667
self .assertRaises (OSError , txt .close ) # exception not swallowed
2626
2668
self .assertTrue (txt .closed )
2669
+ self .assertTrue (txt .buffer .closed )
2670
+ self .assertTrue (closed ) # flush() called
2671
+ self .assertFalse (closed [0 ]) # flush() called before file closed
2672
+ self .assertFalse (closed [1 ])
2627
2673
2628
2674
def test_close_error_on_close (self ):
2629
2675
buffer = self .BytesIO (self .testdata )
0 commit comments