You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by an...@apache.org on 2018/05/23 21:36:49 UTC
[05/10] mesos git commit: Windows: Enabled creating overlapped pipes
with `os::pipe`.
Windows: Enabled creating overlapped pipes with `os::pipe`.
`os::pipe` was using `CreatePipe`, which does not support overlapped
I/O. Now, the implementation of `os::pipe` has been changed to use
`CreateNamedPipe`, which supports overlapped I/O. The named pipe is
created with an unique random name, so it is effectively anonymous.
Review: https://reviews.apache.org/r/66957/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/ebac13d8
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/ebac13d8
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/ebac13d8
Branch: refs/heads/master
Commit: ebac13d83184363dd261b455b878ab613cb85587
Parents: bd4a800
Author: Akash Gupta <ak...@hotmail.com>
Authored: Wed May 23 14:01:26 2018 -0700
Committer: Andrew Schwartzmeyer <an...@schwartzmeyer.com>
Committed: Wed May 23 14:07:46 2018 -0700
----------------------------------------------------------------------
.../stout/include/stout/os/windows/pipe.hpp | 80 +++++++++++++++-----
1 file changed, 63 insertions(+), 17 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/ebac13d8/3rdparty/stout/include/stout/os/windows/pipe.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/os/windows/pipe.hpp b/3rdparty/stout/include/stout/os/windows/pipe.hpp
index a3574fd..7b94889 100644
--- a/3rdparty/stout/include/stout/os/windows/pipe.hpp
+++ b/3rdparty/stout/include/stout/os/windows/pipe.hpp
@@ -14,38 +14,84 @@
#define __STOUT_OS_WINDOWS_PIPE_HPP__
#include <array>
+#include <string>
+#include <stout/check.hpp>
#include <stout/error.hpp>
#include <stout/try.hpp>
+#include <stout/uuid.hpp>
+#include <stout/windows.hpp> // For `windows.h`.
#include <stout/os/int_fd.hpp>
namespace os {
-// Create pipes for interprocess communication. Since the pipes cannot
-// be used directly by Posix `read/write' functions they are wrapped
-// in file descriptors, a process-local concept.
-inline Try<std::array<int_fd, 2>> pipe()
+// Returns an "anonymous" pipe that can be used for interprocess communication.
+// Since anonymous pipes do not support overlapped IO, we emulate it with an
+// uniquely named pipe.
+//
+// NOTE: Overlapped pipes passed to child processes behave weirdly, so we have
+// the ability to create non overlapped pipe handles.
+inline Try<std::array<int_fd, 2>> pipe(
+ bool read_overlapped = true, bool write_overlapped = true)
{
- // Create inheritable pipe, as described in MSDN[1].
- //
- // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa365782(v=vs.85).aspx
- SECURITY_ATTRIBUTES securityAttr;
- securityAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- securityAttr.bInheritHandle = TRUE;
- securityAttr.lpSecurityDescriptor = nullptr;
+ const DWORD read_flags = read_overlapped ? FILE_FLAG_OVERLAPPED : 0;
+ const DWORD write_flags = write_overlapped ? FILE_FLAG_OVERLAPPED : 0;
+ std::wstring name =
+ wide_stringify("\\\\.\\pipe\\mesos-pipe-" + id::UUID::random().toString());
- HANDLE read_handle;
- HANDLE write_handle;
+ // The named pipe name must be at most 256 characters [1]. It doesn't say if
+ // it includes the null terminator, so we limit to 255 to be safe. Since the
+ // UUID name is fixed length, this is just a sanity check.
+ //
+ // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx // NOLINT(whitespace/line_length)
+ CHECK_LE(name.size(), 255);
- const BOOL result =
- ::CreatePipe(&read_handle, &write_handle, &securityAttr, 0);
+ // Create the named pipe. To avoid the time-of-check vs time-of-use attack,
+ // we have the `FILE_FLAG_FIRST_PIPE_INSTANCE` flag to fail if the pipe
+ // already exists.
+ //
+ // TODO(akagup): The buffer size is currently required, since we don't have
+ // IOCP yet. When testing IOCP, it should be 0, but after that, we can try
+ // restoring the buffer for an optimization.
+ const HANDLE read_handle = ::CreateNamedPipeW(
+ name.data(),
+ PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | read_flags,
+ PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
+ 1, // Max pipe instances.
+ 4096, // Inbound buffer size.
+ 4096, // Outbound buffer size.
+ 0, // Pipe timeout for connections.
+ nullptr); // Security attributes (not inheritable).
- if (result == FALSE) {
+ if (read_handle == INVALID_HANDLE_VALUE) {
return WindowsError();
}
- return std::array<int_fd, 2>{int_fd(read_handle), int_fd(write_handle)};
+ // To create a client named pipe, we use the generic `CreateFile` API. We
+ // don't use the other named pipe APIs, since they are used for different
+ // purposes. For example, `ConnectNamedPipe` is similar to a server calling
+ // `accept` for sockets and `CallNamedPipe` is used for message type pipes,
+ // but we want a byte stream pipe.
+ //
+ // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365598%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 // NOLINT(whitespace/line_length)
+ const HANDLE write_handle = ::CreateFileW(
+ name.data(),
+ GENERIC_WRITE,
+ 0,
+ nullptr,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | write_flags,
+ nullptr);
+
+ const WindowsError error;
+ if (write_handle == INVALID_HANDLE_VALUE) {
+ ::CloseHandle(read_handle);
+ return error;
+ }
+
+ return std::array<int_fd, 2>{int_fd(read_handle, read_overlapped),
+ int_fd(write_handle, write_overlapped)};
}
} // namespace os {