Skip to content

Commit

Permalink
Work around compiler crash
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukasa committed Jan 8, 2025
1 parent c7e0477 commit 54e1d46
Showing 1 changed file with 192 additions and 16 deletions.
208 changes: 192 additions & 16 deletions Sources/NIOCore/SocketOptionProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ public typealias NIOLinger = linger
// around. As a result, if you change one, you should probably change them all.
//
// You are welcome to add more helper methods here, but each helper method you add must be tested.
//
// Please note that to work around a Swift compiler issue regarding lookup of the Sendability of
// libc types across modules, the actual calls to `unsafeSetSocketOption` and `unsafeGetSocketOption`
// _must_ be made inside non-`public` non-`@inlinable` methods. Otherwise we'll produce crashes
// in release mode. NIO's integration tests are a good canary for this: if you call your method
// from an alloc counter test in the integration tests, it'll crash if you messed it up.
extension SocketOptionProvider {
/// Sets the socket option SO_LINGER to `value`.
///
Expand All @@ -190,6 +196,176 @@ extension SocketOptionProvider {
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setSoLinger(_ value: linger) -> EventLoopFuture<Void> {
self._setSoLinger(value)
}

/// Gets the value of the socket option SO_LINGER.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getSoLinger() -> EventLoopFuture<NIOLinger> {
self._getSoLinger()
}

/// Sets the socket option IP_MULTICAST_IF to `value`.
///
/// - Parameters:
/// - value: The value to set IP_MULTICAST_IF to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPMulticastIF(_ value: in_addr) -> EventLoopFuture<Void> {
self._setIPMulticastIF(value)
}

/// Gets the value of the socket option IP_MULTICAST_IF.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPMulticastIF() -> EventLoopFuture<in_addr> {
self._getIPMulticastIF()
}

/// Sets the socket option IP_MULTICAST_TTL to `value`.
///
/// - Parameters:
/// - value: The value to set IP_MULTICAST_TTL to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
self._setIPMulticastTTL(value)
}

/// Gets the value of the socket option IP_MULTICAST_TTL.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPMulticastTTL() -> EventLoopFuture<CUnsignedChar> {
self._getIPMulticastTTL()
}

/// Sets the socket option IP_MULTICAST_LOOP to `value`.
///
/// - Parameters:
/// - value: The value to set IP_MULTICAST_LOOP to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
self._setIPMulticastLoop(value)
}

/// Gets the value of the socket option IP_MULTICAST_LOOP.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPMulticastLoop() -> EventLoopFuture<CUnsignedChar> {
self._getIPMulticastLoop()
}

/// Sets the socket option IPV6_MULTICAST_IF to `value`.
///
/// - Parameters:
/// - value: The value to set IPV6_MULTICAST_IF to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
self._setIPv6MulticastIF(value)
}

/// Gets the value of the socket option IPV6_MULTICAST_IF.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPv6MulticastIF() -> EventLoopFuture<CUnsignedInt> {
self._getIPv6MulticastIF()
}

/// Sets the socket option IPV6_MULTICAST_HOPS to `value`.
///
/// - Parameters:
/// - value: The value to set IPV6_MULTICAST_HOPS to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture<Void> {
self._setIPv6MulticastHops(ATM_VALUE_ADDED)
}

/// Gets the value of the socket option IPV6_MULTICAST_HOPS.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPv6MulticastHops() -> EventLoopFuture<CInt> {
self._getIPv6MulticastHops()
}

/// Sets the socket option IPV6_MULTICAST_LOOP to `value`.
///
/// - Parameters:
/// - value: The value to set IPV6_MULTICAST_LOOP to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
self._setIPv6MulticastLoop(value)
}

/// Gets the value of the socket option IPV6_MULTICAST_LOOP.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPv6MulticastLoop() -> EventLoopFuture<CUnsignedInt> {
self._getIPv6MulticastLoop()
}

#if os(Linux) || os(FreeBSD) || os(Android)
/// Gets the value of the socket option TCP_INFO.
///
/// This socket option cannot be set.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getTCPInfo() -> EventLoopFuture<tcp_info> {
self._getTCPInfo()
}
#endif

#if canImport(Darwin)
/// Gets the value of the socket option TCP_CONNECTION_INFO.
///
/// This socket option cannot be set.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getTCPConnectionInfo() -> EventLoopFuture<tcp_connection_info> {
self._getTCPConnectionInfo()
}
#endif

#if os(Linux)
/// Gets the value of the socket option MPTCP_INFO.
///
/// This socket option cannot be set.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getMPTCPInfo() -> EventLoopFuture<mptcp_info> {
self._getMPTCPInfo()
}
#endif

// MARK: Non-public non-inlinable actual implementations for the above.
//
// As discussed above, these are needed to work around a compiler issue
// that was present at least up to the 6.0 compiler series. This prevents
// the specialization being emitted in the caller code, which is unfortunate,
// but it also ensures that we avoid the crash. We should remove these when
// they're no longer needed.

/// Sets the socket option SO_LINGER to `value`.
///
/// - Parameters:
/// - value: The value to set SO_LINGER to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
private func _setSoLinger(_ value: linger) -> EventLoopFuture<Void> {
#if os(WASI)
self.eventLoop.makeFailedFuture(SocketOptionProviderError.unsupported)
#else
Expand All @@ -201,7 +377,7 @@ extension SocketOptionProvider {
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getSoLinger() -> EventLoopFuture<NIOLinger> {
private func _getSoLinger() -> EventLoopFuture<NIOLinger> {
#if os(WASI)
self.eventLoop.makeFailedFuture(SocketOptionProviderError.unsupported)
#else
Expand All @@ -215,15 +391,15 @@ extension SocketOptionProvider {
/// - value: The value to set IP_MULTICAST_IF to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPMulticastIF(_ value: in_addr) -> EventLoopFuture<Void> {
private func _setIPMulticastIF(_ value: in_addr) -> EventLoopFuture<Void> {
self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_if, value: value)
}

/// Gets the value of the socket option IP_MULTICAST_IF.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPMulticastIF() -> EventLoopFuture<in_addr> {
private func _getIPMulticastIF() -> EventLoopFuture<in_addr> {
self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_if)
}

Expand All @@ -233,15 +409,15 @@ extension SocketOptionProvider {
/// - value: The value to set IP_MULTICAST_TTL to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
private func _setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_ttl, value: value)
}

/// Gets the value of the socket option IP_MULTICAST_TTL.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPMulticastTTL() -> EventLoopFuture<CUnsignedChar> {
private func _getIPMulticastTTL() -> EventLoopFuture<CUnsignedChar> {
self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_ttl)
}

Expand All @@ -251,15 +427,15 @@ extension SocketOptionProvider {
/// - value: The value to set IP_MULTICAST_LOOP to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
private func _setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_loop, value: value)
}

/// Gets the value of the socket option IP_MULTICAST_LOOP.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPMulticastLoop() -> EventLoopFuture<CUnsignedChar> {
private func _getIPMulticastLoop() -> EventLoopFuture<CUnsignedChar> {
self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_loop)
}

Expand All @@ -269,15 +445,15 @@ extension SocketOptionProvider {
/// - value: The value to set IPV6_MULTICAST_IF to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
private func _setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_if, value: value)
}

/// Gets the value of the socket option IPV6_MULTICAST_IF.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPv6MulticastIF() -> EventLoopFuture<CUnsignedInt> {
private func _getIPv6MulticastIF() -> EventLoopFuture<CUnsignedInt> {
self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_if)
}

Expand All @@ -287,15 +463,15 @@ extension SocketOptionProvider {
/// - value: The value to set IPV6_MULTICAST_HOPS to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture<Void> {
private func _setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture<Void> {
self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_hops, value: value)
}

/// Gets the value of the socket option IPV6_MULTICAST_HOPS.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPv6MulticastHops() -> EventLoopFuture<CInt> {
private func _getIPv6MulticastHops() -> EventLoopFuture<CInt> {
self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_hops)
}

Expand All @@ -305,15 +481,15 @@ extension SocketOptionProvider {
/// - value: The value to set IPV6_MULTICAST_LOOP to.
/// - Returns: An `EventLoopFuture` that fires when the option has been set,
/// or if an error has occurred.
public func setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
private func _setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_loop, value: value)
}

/// Gets the value of the socket option IPV6_MULTICAST_LOOP.
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getIPv6MulticastLoop() -> EventLoopFuture<CUnsignedInt> {
private func _getIPv6MulticastLoop() -> EventLoopFuture<CUnsignedInt> {
self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_loop)
}

Expand All @@ -324,7 +500,7 @@ extension SocketOptionProvider {
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getTCPInfo() -> EventLoopFuture<tcp_info> {
private func _getTCPInfo() -> EventLoopFuture<tcp_info> {
self.unsafeGetSocketOption(level: .tcp, name: .tcp_info)
}
#endif
Expand All @@ -336,7 +512,7 @@ extension SocketOptionProvider {
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getTCPConnectionInfo() -> EventLoopFuture<tcp_connection_info> {
private func _getTCPConnectionInfo() -> EventLoopFuture<tcp_connection_info> {
self.unsafeGetSocketOption(level: .tcp, name: .tcp_connection_info)
}
#endif
Expand All @@ -348,7 +524,7 @@ extension SocketOptionProvider {
///
/// - Returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
public func getMPTCPInfo() -> EventLoopFuture<mptcp_info> {
private func _getMPTCPInfo() -> EventLoopFuture<mptcp_info> {
self.unsafeGetSocketOption(level: .mptcp, name: .mptcp_info)
}
#endif
Expand Down

0 comments on commit 54e1d46

Please sign in to comment.