@@ -1122,6 +1122,49 @@ def _resume_writing():
11221122 self .assertEqual (transport .get_write_buffer_size (), 0 )
11231123 self .assertTrue (self .protocol .connection_lost .called )
11241124
1125+ def test_write_ready_resume_writing_closes (self ):
1126+ # gh-156512: closing from resume_writing() must not lose the connection twice
1127+ self .sock .send .return_value = 2
1128+
1129+ def _resume_writing ():
1130+ transport .close ()
1131+
1132+ self .protocol .resume_writing .side_effect = _resume_writing
1133+ self .loop .call_exception_handler = mock .Mock ()
1134+
1135+ transport = self .socket_transport ()
1136+ transport .set_write_buffer_limits (high = 1 , low = 0 )
1137+ transport .write (b'data' )
1138+
1139+ self .loop .writers [7 ]._run ()
1140+ test_utils .run_briefly (self .loop )
1141+
1142+ self .assertEqual (self .protocol .connection_lost .call_count , 1 )
1143+ self .loop .call_exception_handler .assert_not_called ()
1144+
1145+ @unittest .skipUnless (selector_events ._HAS_SENDMSG , 'no sendmsg' )
1146+ def test_write_sendmsg_resume_writing_closes (self ):
1147+ # gh-156512: same as above, for the sendmsg write path
1148+ self .sock .send .return_value = 2
1149+ self .sock .sendmsg .return_value = 2
1150+
1151+ def _resume_writing ():
1152+ transport .close ()
1153+
1154+ self .protocol .resume_writing .side_effect = _resume_writing
1155+ self .loop .call_exception_handler = mock .Mock ()
1156+
1157+ transport = self .socket_transport (sendmsg = True )
1158+ transport .set_write_buffer_limits (high = 1 , low = 0 )
1159+ transport .write (b'data' )
1160+
1161+ self .loop .writers [7 ]._run ()
1162+ test_utils .run_briefly (self .loop )
1163+
1164+ self .assertEqual (self .protocol .connection_lost .call_count , 1 )
1165+ self .loop .call_exception_handler .assert_not_called ()
1166+
1167+
11251168class SelectorSocketTransportBufferedProtocolTests (test_utils .TestCase ):
11261169
11271170 def setUp (self ):
0 commit comments