@@ -150,6 +150,30 @@ def test_tcp_client_send(self):
150150 assert not client .send (b"" )
151151 assert client .send (b"1234" ) == 4
152152
153+ def test_tcp_client_send_drops_socket_on_os_error (self ):
154+ """Test that a socket the OS tore down is not left in place as connected."""
155+ client = ModbusTcpClient ("127.0.0.1" )
156+ mock_socket = mock .MagicMock ()
157+ mock_socket .send .side_effect = BrokenPipeError (32 , "Broken pipe" )
158+ client .socket = mock_socket
159+ with pytest .raises (ConnectionException ):
160+ client .send (b"1234" )
161+ assert not client .connected
162+ assert client .socket is None
163+
164+ def test_tcp_client_send_keeps_socket_on_transient_error (self ):
165+ """Test that a transient write error leaves a healthy socket in place."""
166+ client = ModbusTcpClient ("127.0.0.1" )
167+ mock_socket = mock .MagicMock ()
168+ mock_socket .send .side_effect = BlockingIOError (
169+ 11 , "Resource temporarily unavailable"
170+ )
171+ client .socket = mock_socket
172+ with pytest .raises (BlockingIOError ):
173+ client .send (b"1234" )
174+ assert client .connected
175+ assert client .socket is mock_socket
176+
153177 @mock .patch ("pymodbus.client.tcp.time" )
154178 @mock .patch ("pymodbus.client.tcp.select" )
155179 def test_tcp_client_recv (self , mock_select , mock_time ):
0 commit comments