Index: mojo/system/platform_channel_posix.cc |
diff --git a/mojo/system/platform_channel_posix.cc b/mojo/system/platform_channel_posix.cc |
index 0b64620c6bdd08b26c513c6ef4d6174c1c066ee1..4c23657fbd71682ac3aa3defb5cceffd9de48a94 100644 |
--- a/mojo/system/platform_channel_posix.cc |
+++ b/mojo/system/platform_channel_posix.cc |
@@ -9,20 +9,27 @@ |
#include <sys/types.h> |
#include <unistd.h> |
+#include "base/command_line.h" |
#include "base/compiler_specific.h" |
#include "base/logging.h" |
+#include "base/posix/global_descriptors.h" |
+#include "base/strings/string_number_conversions.h" |
namespace mojo { |
namespace system { |
namespace { |
-void CloseIfNecessary(PlatformChannelHandle* handle) { |
- if (!handle->is_valid()) |
- return; |
+const char kMojoChannelDescriptorSwitch[] = "mojo-channel-descriptor"; |
- PCHECK(close(handle->fd) == 0); |
- *handle = PlatformChannelHandle(); |
+bool IsTargetDescriptorUsed( |
+ const base::FileHandleMappingVector& file_handle_mapping, |
+ int target_fd) { |
+ for (size_t i = 0; i < file_handle_mapping.size(); i++) { |
+ if (file_handle_mapping[i].second == target_fd) |
+ return true; |
+ } |
+ return false; |
} |
class PlatformServerChannelPosix : public PlatformServerChannel { |
@@ -59,10 +66,7 @@ PlatformServerChannelPosix::PlatformServerChannelPosix( |
} |
PlatformServerChannelPosix::~PlatformServerChannelPosix() { |
- if (is_valid()) |
- CloseIfNecessary(mutable_handle()); |
- if (client_handle_.is_valid()) |
- CloseIfNecessary(&client_handle_); |
+ client_handle_.CloseIfNecessary(); |
} |
scoped_ptr<PlatformClientChannel> |
@@ -82,13 +86,39 @@ scoped_ptr<PlatformClientChannel> |
void PlatformServerChannelPosix::GetDataNeededToPassClientChannelToChildProcess( |
CommandLine* command_line, |
base::FileHandleMappingVector* file_handle_mapping) const { |
- // TODO(vtl) |
- NOTIMPLEMENTED(); |
+ DCHECK(command_line); |
+ DCHECK(file_handle_mapping); |
+ // This is an arbitrary sanity check. (Note that this guarantees that the loop |
+ // below will terminate sanely.) |
+ CHECK_LT(file_handle_mapping->size(), 1000u); |
+ |
+ DCHECK(client_handle_.is_valid()); |
+ |
+ // Find a suitable FD to map our client handle to in the child process. |
+ // This has quadratic time complexity in the size of |*file_handle_mapping|, |
+ // but |*file_handle_mapping| should be very small (usually/often empty). |
+ int target_fd = base::GlobalDescriptors::kBaseDescriptor; |
+ while (IsTargetDescriptorUsed(*file_handle_mapping, target_fd)) |
+ target_fd++; |
+ |
+ file_handle_mapping->push_back(std::pair<int, int>(client_handle_.fd, |
+ target_fd)); |
+ // Log a warning if the command line already has the switch, but "clobber" it |
+ // anyway, since it's reasonably likely that all the switches were just copied |
+ // from the parent. |
+ LOG_IF(WARNING, command_line->HasSwitch(kMojoChannelDescriptorSwitch)) |
+ << "Child command line already has switch --" |
+ << kMojoChannelDescriptorSwitch << "=" |
+ << command_line->GetSwitchValueASCII(kMojoChannelDescriptorSwitch); |
+ // (Any existing switch won't actually be removed from the command line, but |
+ // the last one appended takes precedence.) |
+ command_line->AppendSwitchASCII(kMojoChannelDescriptorSwitch, |
+ base::IntToString(target_fd)); |
} |
void PlatformServerChannelPosix::ChildProcessLaunched() { |
- // TODO(vtl) |
- NOTIMPLEMENTED(); |
+ DCHECK(client_handle_.is_valid()); |
+ client_handle_.CloseIfNecessary(); |
} |
} // namespace |
@@ -110,9 +140,17 @@ scoped_ptr<PlatformServerChannel> PlatformServerChannel::Create( |
scoped_ptr<PlatformClientChannel> |
PlatformClientChannel::CreateFromParentProcess( |
const CommandLine& command_line) { |
- // TODO(vtl) |
- NOTIMPLEMENTED(); |
- return scoped_ptr<PlatformClientChannel>(); |
+ std::string client_fd_string = |
+ command_line.GetSwitchValueASCII(kMojoChannelDescriptorSwitch); |
+ int client_fd = -1; |
+ if (client_fd_string.empty() || |
+ !base::StringToInt(client_fd_string, &client_fd) || |
+ client_fd < base::GlobalDescriptors::kBaseDescriptor) { |
+ LOG(ERROR) << "Missing or invalid --" << kMojoChannelDescriptorSwitch; |
+ return scoped_ptr<PlatformClientChannel>(); |
+ } |
+ |
+ return CreateFromHandle(PlatformChannelHandle(client_fd)); |
} |
} // namespace system |