Implemented `net::socket()` for Windows using `WSASocket`.

Rather than reusing the existing `net::socket()` wrapper for Windows,
the original wrapper was moved to `posix/socket.hpp`, and a new wrapper
was written in `windows/socket.hpp` which uses `::WSASocket()` instead
of `::socket()` and takes an optional set of Windows socket flags.

We enable `WSA_FLAG_OVERLAPPED` so that the socket supports overlapped
I/O operations (the default behavior of `::socket()`; MSDN states that
most sockets should be created with this flag set, so it is a reasonable
default.

Furthermore, we enable `WSA_FLAG_NO_HANDLE_INHERIT`, which disables
inheritance of socket handles. This is set by default because it is not
possible to change afterwards, we never use inheritable sockets, and we
do not want children to inherit our sockets. This fixes bugs due to
child processes inadvertantly inheriting sockets. For example, in the
recovery process of the Mesos agent, executors were unable to
re-register because of leaked sockets, preventing communication to the
new agent.

Review: https://reviews.apache.org/r/65405


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/32c300e5
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/32c300e5
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/32c300e5

Branch: refs/heads/master
Commit: 32c300e534aab80897238649fb1b1b36380475c1
Parents: 9bde2ae
Author: Andrew Schwartzmeyer <and...@schwartzmeyer.com>
Authored: Mon Jan 22 15:42:29 2018 -0800
Committer: Andrew Schwartzmeyer <and...@schwartzmeyer.com>
Committed: Fri Feb 9 12:03:16 2018 -0800

----------------------------------------------------------------------
 .../stout/include/stout/os/posix/socket.hpp     | 23 +++++++++++++++++
 3rdparty/stout/include/stout/os/socket.hpp      | 25 -------------------
 .../stout/include/stout/os/windows/socket.hpp   | 26 ++++++++++++++++++++
 3 files changed, 49 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/32c300e5/3rdparty/stout/include/stout/os/posix/socket.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/os/posix/socket.hpp 
b/3rdparty/stout/include/stout/os/posix/socket.hpp
index bab0b80..5557394 100644
--- a/3rdparty/stout/include/stout/os/posix/socket.hpp
+++ b/3rdparty/stout/include/stout/os/posix/socket.hpp
@@ -28,6 +28,29 @@ using ::connect;
 using ::recv;
 using ::send;
 
+
+// Returns a socket file descriptor for the specified options.
+// NOTE: on OS X, the returned socket will have the SO_NOSIGPIPE option set.
+inline Try<int_fd> socket(int family, int type, int protocol)
+{
+  int_fd s;
+  if ((s = ::socket(family, type, protocol)) < 0) {
+    return ErrnoError();
+  }
+
+#ifdef __APPLE__
+  // Disable SIGPIPE via setsockopt because OS X does not support
+  // the MSG_NOSIGNAL flag on send(2).
+  const int enable = 1;
+  if (setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &enable, sizeof(int)) == -1) {
+    return ErrnoError();
+  }
+#endif // __APPLE__
+
+  return s;
+}
+
+
 // The error indicates the last socket operation has been
 // interupted, the operation can be restarted immediately.
 inline bool is_restartable_error(int error)

http://git-wip-us.apache.org/repos/asf/mesos/blob/32c300e5/3rdparty/stout/include/stout/os/socket.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/os/socket.hpp 
b/3rdparty/stout/include/stout/os/socket.hpp
index 2ca4465..54e19e6 100644
--- a/3rdparty/stout/include/stout/os/socket.hpp
+++ b/3rdparty/stout/include/stout/os/socket.hpp
@@ -24,29 +24,4 @@
 #include <stout/os/posix/socket.hpp>
 #endif // __WINDOWS__
 
-namespace net {
-
-// Returns a socket file descriptor for the specified options.
-// NOTE: on OS X, the returned socket will have the SO_NOSIGPIPE option set.
-inline Try<int_fd> socket(int family, int type, int protocol)
-{
-  int_fd s;
-  if ((s = ::socket(family, type, protocol)) < 0) {
-    return ErrnoError();
-  }
-
-#ifdef __APPLE__
-  // Disable SIGPIPE via setsockopt because OS X does not support
-  // the MSG_NOSIGNAL flag on send(2).
-  const int enable = 1;
-  if (setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &enable, sizeof(int)) == -1) {
-    return ErrnoError();
-  }
-#endif // __APPLE__
-
-  return s;
-}
-
-} // namespace net {
-
 #endif // __STOUT_OS_SOCKET_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/32c300e5/3rdparty/stout/include/stout/os/windows/socket.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/os/windows/socket.hpp 
b/3rdparty/stout/include/stout/os/windows/socket.hpp
index 020c5e2..259b05b 100644
--- a/3rdparty/stout/include/stout/os/windows/socket.hpp
+++ b/3rdparty/stout/include/stout/os/windows/socket.hpp
@@ -16,8 +16,12 @@
 #include <glog/logging.h>
 
 #include <stout/abort.hpp>
+#include <stout/try.hpp>
+#include <stout/error.hpp>
 #include <stout/windows.hpp> // For `WinSock2.h`.
 
+#include <stout/os/int_fd.hpp>
+
 #include <stout/os/windows/fd.hpp>
 
 
@@ -107,6 +111,24 @@ inline bool is_retryable_error(int error) { return (error 
== WSAEWOULDBLOCK); }
 inline bool is_inprogress_error(int error) { return (error == WSAEWOULDBLOCK); 
}
 
 
+// Returns a socket file descriptor for the specified options.
+//
+// NOTE: We default to no inheritance because we never inherit sockets.
+// Overlapped I/O is enabled to match the default behavior of `::socket`.
+inline Try<int_fd> socket(
+    int family,
+    int type,
+    int protocol,
+    DWORD flags = WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT)
+{
+  SOCKET s = ::WSASocketW(family, type, protocol, nullptr, 0, flags);
+  if (s == INVALID_SOCKET) {
+    return WindowsSocketError();
+  }
+
+  return s;
+}
+
 // NOTE: The below wrappers are used to silence some implicit
 // type-casting warnings.
 
@@ -117,6 +139,10 @@ inline os::WindowsFD accept(
 }
 
 
+// NOTE: If `::bind` or `::connect` fail, they return `SOCKET_ERROR`, which is
+// defined to be `-1`. Therefore, the error checking logic of `result < 0` used
+// on POSIX will also work on Windows.
+
 inline int bind(
     const os::WindowsFD& fd, const sockaddr* addr, socklen_t addrlen)
 {

Reply via email to