Windows: Made `protobuf::write()` use CRT file descriptor explicitly.

This is another edge case where a third-party library (protobuf)
requires a CRT integer file descriptor. Thus we duplicate the `int_fd`
and then explicitly allocate via `crt()`, which requires that we also
manually close it via `_close()`.

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


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

Branch: refs/heads/master
Commit: c516741a1348eee2d6b7e257fc2127f7d47c2a69
Parents: 9326f8f
Author: Andrew Schwartzmeyer <[email protected]>
Authored: Tue Mar 20 22:26:27 2018 -0700
Committer: Andrew Schwartzmeyer <[email protected]>
Committed: Tue May 1 18:36:04 2018 -0700

----------------------------------------------------------------------
 3rdparty/stout/include/stout/protobuf.hpp | 27 ++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/c516741a/3rdparty/stout/include/stout/protobuf.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/protobuf.hpp 
b/3rdparty/stout/include/stout/protobuf.hpp
index 2fa5072..1d03e1e 100644
--- a/3rdparty/stout/include/stout/protobuf.hpp
+++ b/3rdparty/stout/include/stout/protobuf.hpp
@@ -52,6 +52,10 @@
 #include <stout/os/read.hpp>
 #include <stout/os/write.hpp>
 
+#ifdef __WINDOWS__
+#include <stout/os/dup.hpp>
+#endif // __WINDOWS__
+
 namespace protobuf {
 
 // TODO(bmahler): Re-use stout's 'recordio' facilities here. Note
@@ -80,12 +84,31 @@ inline Try<Nothing> write(int_fd fd, const 
google::protobuf::Message& message)
   }
 
 #ifdef __WINDOWS__
-  if (!message.SerializeToFileDescriptor(fd.crt())) {
+  // NOTE: On Windows, we need to explicitly allocate a CRT file
+  // descriptor because the Protobuf library requires it. Because
+  // users of `protobuf::write` are likely to call `os::close` on the
+  // `fd` we were given, we need to duplicate it before allocating the
+  // CRT fd. This is because once the CRT fd is allocated, it must be
+  // closed with `_close` instead of `os::close`. Since we need to
+  // call `_close` here, we duplicate the fd to prevent the users call
+  // of `os::close` from closing twice.
+  Try<int_fd> dup = os::dup(fd);
+  if (dup.isError()) {
+    return Error("Failed to duplicate handle: " + dup.error());
+  }
+
+  int crt = dup->crt();
+
+  if (!message.SerializeToFileDescriptor(crt)) {
+    ::_close(crt);
+    return Error("Failed to write/serialize message");
+  }
+  ::_close(crt);
 #else
   if (!message.SerializeToFileDescriptor(fd)) {
-#endif
     return Error("Failed to write/serialize message");
   }
+#endif
 
   return Nothing();
 }

Reply via email to