Skip to content

Commit f5a8b85

Browse files
committed
Not retry calling close(...) when EINTR is reported.
Motivation: Usually we retry the syscall when EINTR is reported. This is not safe in the case of close(...) as the file descriptor may already be closed. The problem arise if this was the case and we retry it and the file descriptor is already reused again. In this case we would close a wrong file descriptor. See: - https://bugs.chromium.org/p/chromium/issues/detail?id=269623 - https://lwn.net/Articles/576478/ Modifications: Ignore EINTR on close(...) and just assume the FD was closed. Result: Not possible to close the wrong file descriptor when close(...) reports EINTR.
1 parent f58e831 commit f5a8b85

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

Sources/NIO/System.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,20 @@ internal enum Posix {
184184

185185
@inline(never)
186186
public static func close(descriptor: CInt) throws {
187-
_ = try wrapSyscall {
188-
sysClose(descriptor)
187+
let res = sysClose(descriptor)
188+
if res == -1 {
189+
let err = errno
190+
191+
// There is really nothing "sane" we can do when EINTR was reported on close.
192+
// So just ignore it and "assume" everything is fine == we closed the file descriptor.
193+
//
194+
// For more details see:
195+
// - https://bugs.chromium.org/p/chromium/issues/detail?id=269623
196+
// - https://lwn.net/Articles/576478/
197+
if err != EINTR {
198+
assert(!isBlacklistedErrno(err), "blacklisted errno \(err) \(strerror(err)!)")
199+
throw IOError(errnoCode: err, function: function)
200+
}
189201
}
190202
}
191203

0 commit comments

Comments
 (0)