@@ -1008,6 +1008,39 @@ def test_bufsize_is_none(self):
10081008 p = subprocess .Popen ([sys .executable , "-c" , "pass" ], bufsize = None )
10091009 self .assertEqual (p .wait (), 0 )
10101010
1011+ def _test_bufsize_equal_one (self , line , expected , universal_newlines ):
1012+ # subprocess may deadlock with bufsize=1, see issue #21332
1013+ with subprocess .Popen ([sys .executable , "-c" , "import sys;"
1014+ "sys.stdout.write(sys.stdin.readline());"
1015+ "sys.stdout.flush()" ],
1016+ stdin = subprocess .PIPE ,
1017+ stdout = subprocess .PIPE ,
1018+ stderr = subprocess .DEVNULL ,
1019+ bufsize = 1 ,
1020+ universal_newlines = universal_newlines ) as p :
1021+ p .stdin .write (line ) # expect that it flushes the line in text mode
1022+ os .close (p .stdin .fileno ()) # close it without flushing the buffer
1023+ read_line = p .stdout .readline ()
1024+ try :
1025+ p .stdin .close ()
1026+ except OSError :
1027+ pass
1028+ p .stdin = None
1029+ self .assertEqual (p .returncode , 0 )
1030+ self .assertEqual (read_line , expected )
1031+
1032+ def test_bufsize_equal_one_text_mode (self ):
1033+ # line is flushed in text mode with bufsize=1.
1034+ # we should get the full line in return
1035+ line = "line\n "
1036+ self ._test_bufsize_equal_one (line , line , universal_newlines = True )
1037+
1038+ def test_bufsize_equal_one_binary_mode (self ):
1039+ # line is not flushed in binary mode with bufsize=1.
1040+ # we should get empty response
1041+ line = b'line' + os .linesep .encode () # assume ascii-based locale
1042+ self ._test_bufsize_equal_one (line , b'' , universal_newlines = False )
1043+
10111044 def test_leaking_fds_on_error (self ):
10121045 # see bug #5179: Popen leaks file descriptors to PIPEs if
10131046 # the child fails to execute; this will eventually exhaust
0 commit comments