| 3750 | self._socket = sock_obj |
| 3751 | |
| 3752 | def terminate(self): |
| 3753 | import socket as _socket_mod |
| 3754 | |
| 3755 | # shutdown() sends TCP FIN to the server (triggering |
| 3756 | # server-side disconnect detection) and interrupts any |
| 3757 | # pending blocking reads on other threads immediately. |
| 3758 | try: |
| 3759 | self._socket.shutdown(_socket_mod.SHUT_RDWR) |
| 3760 | except OSError: |
| 3761 | pass # Safe to ignore — socket may already be closed |
| 3762 | # Close the file wrapper — makefile() holds its own |
| 3763 | # reference to the fd, so socket.close() alone won't |
| 3764 | # release the OS resource until the wrapper is closed too. |
| 3765 | try: |
| 3766 | self.stdin.close() |
| 3767 | except OSError: |
| 3768 | pass # Safe to ignore — already closed |
| 3769 | try: |
| 3770 | self._socket.close() |
| 3771 | except OSError: |
| 3772 | pass # Safe to ignore — already closed |
| 3773 | |
| 3774 | def kill(self): |
| 3775 | self.terminate() |