Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion src/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,42 @@ Status SockSetTcpNoDelay(int fd, int val) {
return Status::OK();
}

Status SockSetTcpKeepalive(int fd, int val) {
Status SockSetTcpKeepalive(int fd, int interval) {
int val = 1;
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1) {
return Status(Status::NotOK, strerror(errno));
}

#ifdef __linux__
// Default settings are more or less garbage, with the keepalive time
// set to 7200 by default on Linux. Modify settings to make the feature
// actually useful.

// Send first probe after interval.
val = interval;
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
return Status(Status::NotOK, std::string("setsockopt TCP_KEEPIDLE: ")+strerror(errno));
}

// Send next probes after the specified interval. Note that we set the
// delay as interval / 3, as we send three probes before detecting
// an error (see the next setsockopt call).
val = interval / 3;
if (val == 0) val = 1;
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {
return Status(Status::NotOK, std::string("setsockopt TCP_KEEPINTVL: ")+strerror(errno));
}

// Consider the socket in error state after three we send three ACK
// probes without getting a reply.
val = 3;
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
return Status(Status::NotOK, std::string("setsockopt TCP_KEEPCNT: ")+strerror(errno));
}
#else
((void) interval); // Avoid unused var warning for non Linux systems.
#endif

return Status::OK();
}

Expand Down
2 changes: 1 addition & 1 deletion src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ sockaddr_in NewSockaddrInet(const std::string &host, uint32_t port);
Status SockConnect(std::string host, uint32_t port, int *fd);
Status SockConnect(std::string host, uint32_t port, int *fd, uint64_t conn_timeout, uint64_t timeout = 0);
Status SockSetTcpNoDelay(int fd, int val);
Status SockSetTcpKeepalive(int fd, int val);
Status SockSetTcpKeepalive(int fd, int interval);
Status SockSend(int fd, const std::string &data);
Status SockReadLine(int fd, std::string *data);
int GetPeerAddr(int fd, std::string *addr, uint32_t *port);
Expand Down
2 changes: 1 addition & 1 deletion src/worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void Worker::newConnection(evconnlistener *listener, evutil_socket_t fd,
<< " from port: " << worker->svr_->GetConfig()->port << " thread #"
<< worker->tid_;
}
auto s = Util::SockSetTcpKeepalive(fd, 1);
auto s = Util::SockSetTcpKeepalive(fd, 120);
if (!s.IsOK()) {
LOG(ERROR) << "[worker] Failed to set tcp-keepalive, err:" << s.Msg();
evutil_closesocket(fd);
Expand Down