SiriusTL666 opened a new pull request, #13009: URL: https://github.com/apache/seatunnel/pull/13009
### Purpose of this pull request The FTP file system creates its client and calls `connect(host, port)` without ever setting a read timeout. `FTPClient` inherits `_timeout_` from `SocketClient`, and that field defaults to `0`, which means **wait indefinitely**. So a server that accepts the TCP connection but never sends a reply leaves the calling thread parked in a read with no deadline. That covers a stalled server, a firewall or load balancer that accepts the connection and silently drops the traffic, and a server that stops answering halfway through a listing. Nothing surfaces at the job level: the thread is blocked, so there is no error to retry and no progress to report. The connect step itself is not the problem. `SocketClient` already defaults `connectTimeout` to 60000 ms, so an unreachable host fails on its own. The unbounded wait is specifically the control-channel read: the greeting, the login exchange, and every listing or command reply. ### Does this PR introduce _any_ user-facing change? Yes. A new `control_timeout` option (milliseconds, default `60000`) bounds each control-connection reply. - Declared on **both** source and sink, because reads and writes share the same control channel. Declaring it on only one side would leave the other with the unbounded wait. - Applied **before** `connect()`, so the greeting is covered. Applying it after would leave exactly the first read unprotected, which is the read that hangs most often. - `control_timeout = 0` restores the previous wait-indefinitely behaviour. - Recorded in the `dev` section of `incompatible-changes.md` (EN and ZH), because a job that previously hung silently in `RUNNING` now fails with a timeout. ### Does this PR introduce _any_ user-facing change? (second part) Two handshake failures left the client socket open: a rejected greeting (`!FTPReply.isPositiveCompletion`) and a refused login both threw without disconnecting. The TCP connection is already established at those points, so the connection stayed pinned on the server until the server gave up on it. Both paths now disconnect before throwing. The reply code for the login failure is captured before `disconnect()` so the error message still reports the server's code. ### How was this patch tested? Local, JDK 17, `connector-file-ftp` module: **26/26 pass** (`FtpFileFactoryTest` 4, `SeaTunnelFTPFileSystemTest` 13, new `SeaTunnelFTPFileSystemTimeoutTest` 9). `spotless:check` passes. The timeout cannot be observed through a getter, so the new tests intercept construction with Mockito and assert: - the exact value passed to `setDefaultTimeout` for the default and for a configured value; - that it is called **before** `connect`, via `InOrder`, which is what decides whether the greeting is protected; - that `0` is passed through unchanged as the opt-out; - that both the rejected-greeting and refused-login paths call `disconnect`; - that a successful call still disconnects exactly once, so the new failure-path disconnect does not double-release; - that the option is declared in both factories, and that the value reaches the Hadoop configuration map. Both fixes were reverse-verified. Reverting `setDefaultTimeout` turns 4 tests red (`Wanted but not invoked`); reverting the two `disconnect` calls turns 2 tests red. Behaviour was also confirmed against a real `FTPClient` before writing the fix: with a server that sends a `220` greeting and then goes silent, `login()` was still blocked after 6 s with no timeout set, and threw `SocketTimeoutException` at 2.0 s with `setDefaultTimeout(2000)`. The same check showed `connectTimeout` already defaulting to 60000, which is why this change only targets the control-channel read. ### Check list - [x] I have read the [Contributing Guide](https://seatunnel.apache.org/community/contribute) - [x] New feature and improvements added - [ ] Bug fixes (mark `x`) if this PR fixes a bug - [x] Docs updated (connector tables EN/ZH, `incompatible-changes.md` EN/ZH) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
