Skip to content

Commit 55a27f5

Browse files
authored
Kqueue: sendfile EINTR doesn't advance offset — data duplication (#16544)
Motivation: BSD/macOS sendfile passes the offset by value (unlike Linux which takes off_t*). When interrupted (EINTR), sbytes reports how many bytes were sent before the signal. Modifications: - Advance off so the next iteration resumes from where we left off, not from the start. Result: Fix possible data corruption when using sendfile and EINTR is observed
1 parent fa8ca6a commit 55a27f5

1 file changed

Lines changed: 6 additions & 1 deletion

File tree

transport-native-kqueue/src/main/c/netty_kqueue_bsdsocket.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,17 @@ static jlong netty_kqueue_bsdsocket_sendFile(JNIEnv* env, jclass clazz, jint soc
7373
sbytes = 0;
7474
res = sendfile(srcFd, socketFd, base_off + off, len, NULL, &sbytes, 0);
7575
#endif
76+
// BSD/macOS sendfile passes the offset by value (unlike Linux which takes off_t*).
77+
// When interrupted (EINTR), sbytes reports how many bytes were sent before the signal.
78+
// Advance off so the next iteration resumes from where we left off, not from the start.
79+
off += sbytes;
7680
len -= sbytes;
7781
} while (res < 0 && ((err = errno) == EINTR));
7882
sbytes = lenBefore - len;
7983
if (sbytes > 0) {
8084
// update the transferred field in DefaultFileRegion
81-
(*env)->SetLongField(env, fileRegion, transferredFieldId, off + sbytes);
85+
// off has already been advanced by sbytes inside the loop, so it equals the new total.
86+
(*env)->SetLongField(env, fileRegion, transferredFieldId, off);
8287
return sbytes;
8388
}
8489
return res < 0 ? -err : 0;

0 commit comments

Comments
 (0)