THRIFT-3080: fix connection leak of C++ Nonblocking Server while huge number connections are accepted and unix socket stream fd is busy.
diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp
index 587560c..31bc34b 100644
--- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp
+++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp
@@ -28,6 +28,7 @@
#include <thrift/transport/PlatformSocket.h>
#include <iostream>
+#include <poll.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@@ -1393,9 +1394,39 @@
return false;
}
- const int kSize = sizeof(conn);
- if (send(fd, const_cast_sockopt(&conn), kSize, 0) != kSize) {
- return false;
+ int ret = -1;
+ struct pollfd pfd = {fd, POLLOUT, 0};
+ int kSize = sizeof(conn);
+ const char * pos = (const char *)const_cast_sockopt(&conn);
+
+ while (kSize > 0) {
+ pfd.revents = 0;
+ ret = poll(&pfd, 1, -1);
+ if (ret < 0) {
+ return false;
+ } else if (ret == 0) {
+ continue;
+ }
+
+ if (pfd.revents & POLLHUP || pfd.revents & POLLERR) {
+ ::close(fd);
+ return false;
+ }
+
+ if (pfd.revents & POLLOUT) {
+ ret = send(fd, pos, kSize, 0);
+ if (ret < 0) {
+ if (errno == EAGAIN) {
+ continue;
+ }
+
+ ::close(fd);
+ return false;
+ }
+
+ kSize -= ret;
+ pos += ret;
+ }
}
return true;