diff --git a/src/unix/core.c b/src/unix/core.c index 25249bcb..1611cba2 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -1922,7 +1922,7 @@ int uv__sock_reuseport(int fd) { #elif (defined(__linux__) || \ defined(_AIX73) || \ (defined(__DragonFly__) && __DragonFly_version >= 300600) || \ - (defined(__sun) && defined(SO_FLOW_NAME))) && \ + (defined(UV__SOLARIS_11_4) && UV__SOLARIS_11_4)) && \ defined(SO_REUSEPORT) /* On Linux 3.9+, the SO_REUSEPORT implementation distributes connections * evenly across all of the threads (or processes) that are blocked in @@ -1938,9 +1938,7 @@ int uv__sock_reuseport(int fd) { * Solaris 11 supported SO_REUSEPORT, but it's implemented only for * binding to the same address and port, without load balancing. * Solaris 11.4 extended SO_REUSEPORT with the capability of load balancing. - * Since it's impossible to detect the Solaris 11.4 version via OS macros, - * so we check the presence of the socket option SO_FLOW_NAME that was first - * introduced to Solaris 11.4. */ + */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) return UV__ERR(errno); #else diff --git a/src/unix/internal.h b/src/unix/internal.h index 1c0c88c7..a8ff3909 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -483,4 +483,16 @@ typedef struct { int uv__get_constrained_cpu(uv__cpu_constraint* constraint); #endif +#ifdef __sun +#ifdef SO_FLOW_NAME +/* Since it's impossible to detect the Solaris 11.4 version via OS macros, + * so we check the presence of the socket option SO_FLOW_NAME that was first + * introduced to Solaris 11.4 and define a custom macro for determining 11.4. + */ +#define UV__SOLARIS_11_4 (1) +#else +#define UV__SOLARIS_11_4 (0) +#endif +#endif + #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/src/unix/tcp.c b/src/unix/tcp.c index eba8c99f..98970d75 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -458,6 +458,14 @@ int uv__tcp_nodelay(int fd, int on) { } +#if (defined(UV__SOLARIS_11_4) && !UV__SOLARIS_11_4) || \ + (defined(__DragonFly__) && __DragonFly_version < 500702) +/* DragonFlyBSD <500702 and Solaris <11.4 require millisecond units + * for TCP keepalive options. */ +#define UV_KEEPALIVE_FACTOR(x) (x *= 1000) +#else +#define UV_KEEPALIVE_FACTOR(x) +#endif int uv__tcp_keepalive(int fd, int on, unsigned int delay) { int idle; int intvl; @@ -507,6 +515,8 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) { if (idle > 10*24*60*60) idle = 10*24*60*60; + UV_KEEPALIVE_FACTOR(idle); + /* `TCP_KEEPIDLE`, `TCP_KEEPINTVL`, and `TCP_KEEPCNT` were not available on Solaris * until version 11.4, but let's take a chance here. */ #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT) @@ -514,6 +524,7 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) { return UV__ERR(errno); intvl = 10; /* required at least 10 seconds */ + UV_KEEPALIVE_FACTOR(intvl); if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl))) return UV__ERR(errno); @@ -524,30 +535,33 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) { /* Fall back to the first implementation of tcp-alive mechanism for older Solaris, * simulate the tcp-alive mechanism on other platforms via `TCP_KEEPALIVE_THRESHOLD` + `TCP_KEEPALIVE_ABORT_THRESHOLD`. */ - idle *= 1000; /* kernel expects milliseconds */ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, &idle, sizeof(idle))) return UV__ERR(errno); /* Note that the consequent probes will not be sent at equal intervals on Solaris, * but will be sent using the exponential backoff algorithm. */ - int time_to_abort = 10*1000; /* 10 seconds, kernel expects milliseconds */ + int time_to_abort = 10; /* 10 seconds */ + UV_KEEPALIVE_FACTOR(time_to_abort); if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, &time_to_abort, sizeof(time_to_abort))) return UV__ERR(errno); #endif #else /* !defined(__sun) */ + idle = delay; + UV_KEEPALIVE_FACTOR(idle); #ifdef TCP_KEEPIDLE - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) + if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle))) return UV__ERR(errno); #elif defined(TCP_KEEPALIVE) /* Darwin/macOS uses TCP_KEEPALIVE in place of TCP_KEEPIDLE. */ - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay))) + if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &idle, sizeof(idle))) return UV__ERR(errno); #endif #ifdef TCP_KEEPINTVL intvl = 1; /* 1 second; same as default on Win32 */ + UV_KEEPALIVE_FACTOR(intvl); if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl))) return UV__ERR(errno); #endif