Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixed: Fix usb fd not being sent due to refactoring in 3c1a6be
This is a minor refactor of the WithAncillaryFd ResultReturner that achieves two goals: 1. The usb fd is no longer closed before the message is sent over the socket. This resolves #643 2. We queue the fd to be sent (using setFileDescriptorsForSend) and then write `@` as data and then flush the output message in a single operation so that fd is actually sent. Writing `@` is required because as per docs "The file descriptors will be sent with the next write of normal data, and will be delivered in a single ancillary message.". The `@` character is not special, it is just the chosen character expected as the message by the native `termux-api` command when a fd is sent. - https://developer.android.com/reference/android/net/LocalSocket#setFileDescriptorsForSend(java.io.FileDescriptor[]) - https://github.com/termux/termux-api-package/blob/e62bdadea3f26b60430bb85248f300fee68ecdcc/termux-api.c#L358 Explanation for why this got broken in 3c1a6be by @agnostic-apollo at #644 (comment): Previously, in `UsbApi`, the fd was only temporarily stored in `WithAncillaryFd`, but not actually sent or passed to `LocalSocket`, and then a `@` was written, possibly in attempts to send it, even though like I said, it wasn't passed to `LocalSocket` with `setFileDescriptorsForSend()` yet, so it was a pointless write, but worked due to autoflush on `close()` (check below). After this, when `writeResult()` returned, then `fd` was passed to `LocalSocket`, but still not sent, since no data was written after it. - https://github.com/termux/termux-api/blob/3bea194249586a7dcb143e66b46c1694cb6ca21a/app/src/main/java/com/termux/api/apis/UsbAPI.java#L69-L70 - https://github.com/termux/termux-api/blob/3c1a6be86ff0768fa8be029267fbe96dd7fbfb7f/app/src/main/java/com/termux/api/util/ResultReturner.java#L173-L181 Previously, before 3c1a6be, the `PrintWriter` in `ResultReturner` was using java `try-with-resources`, which automatically closes when `try` gets out of scope. Additionally, when `new PrintWriter(outputSocket.getOutputStream()` is called, it uses a `BufferedWriter` internally, which when closed, automatically flushes. What this would do is actually send the socket that was previously passed to `LocalSocket`. Moreover, `PrintWriter` was also closed before `fd` was closed since `try-with-resources` finished before, but after the commit, it was closed afterwards, causing the issue. - https://cs.android.com/android/platform/superproject/+/android-14.0.0_r1:libcore/ojluni/src/main/java/java/io/PrintWriter.java;l=164 - https://cs.android.com/android/platform/superproject/+/android-14.0.0_r1:libcore/ojluni/src/main/java/java/io/BufferedWriter.java;l=268 - https://cs.android.com/android/platform/superproject/main/+/main:libcore/ojluni/src/main/java/java/io/Writer.java;l=412 Closes #643
- Loading branch information