Backed out 2 changesets (bug 1767514) for causing mochitest failures on browser_fullscreen_warning.js CLOSED TREE

Backed out changeset 53ebc3f919ba (bug 1767514)
Backed out changeset 62befea29e73 (bug 1767514)
This commit is contained in:
Cristian Tuns
2022-05-06 19:06:35 -04:00
parent f3ea0d04b1
commit 9bf4d84bed
6 changed files with 57 additions and 158 deletions

View File

@@ -195,13 +195,11 @@ void Channel::ChannelImpl::Init(Mode mode, Listener* listener) {
// Verify that we fit in a "quantum-spaced" jemalloc bucket.
static_assert(sizeof(*this) <= 512, "Exceeded expected size class");
MOZ_RELEASE_ASSERT(kControlBufferHeaderSize >= CMSG_SPACE(0));
MOZ_RELEASE_ASSERT(kControlBufferSize >=
CMSG_SPACE(sizeof(int) * kControlBufferMaxFds));
DCHECK(kControlBufferHeaderSize >= CMSG_SPACE(0));
mode_ = mode;
is_blocked_on_write_ = false;
partial_write_.reset();
partial_write_iter_.reset();
input_buf_offset_ = 0;
input_buf_ = mozilla::MakeUnique<char[]>(Channel::kReadBufferSize);
input_cmsg_buf_ = mozilla::MakeUnique<char[]>(kControlBufferSize);
@@ -573,9 +571,11 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
struct msghdr msgh = {0};
char cmsgBuf[kControlBufferSize];
static const int tmp =
CMSG_SPACE(sizeof(int[IPC::Message::MAX_DESCRIPTORS_PER_MESSAGE]));
char buf[tmp];
if (partial_write_.isNothing()) {
if (partial_write_iter_.isNothing()) {
#if defined(OS_MACOSX)
if (!TransferMachPorts(*msg)) {
return false;
@@ -583,30 +583,44 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
#endif
Pickle::BufferList::IterImpl iter(msg->Buffers());
MOZ_DIAGNOSTIC_ASSERT(!iter.Done(), "empty message");
partial_write_.emplace(PartialWrite{iter, msg->attached_handles_});
partial_write_iter_.emplace(iter);
}
if (partial_write_->iter_.Done()) {
MOZ_DIAGNOSTIC_ASSERT(false, "partial_write_->iter_ should not be done");
if (partial_write_iter_.ref().Done()) {
MOZ_DIAGNOSTIC_ASSERT(false, "partial_write_iter_ should not be null");
// report a send error to our caller, which will close the channel.
return false;
}
if (partial_write_->iter_.Data() == msg->Buffers().Start()) {
if (partial_write_iter_.value().Data() == msg->Buffers().Start()) {
AddIPCProfilerMarker(*msg, other_pid_, MessageDirection::eSending,
MessagePhase::TransferStart);
if (!msg->attached_handles_.IsEmpty()) {
// This is the first chunk of a message which has descriptors to send
if (msg->attached_handles_.Length() >
IPC::Message::MAX_DESCRIPTORS_PER_MESSAGE) {
struct cmsghdr* cmsg;
const unsigned num_fds = msg->attached_handles_.Length();
if (num_fds > IPC::Message::MAX_DESCRIPTORS_PER_MESSAGE) {
MOZ_DIAGNOSTIC_ASSERT(false, "Too many file descriptors!");
CHROMIUM_LOG(FATAL) << "Too many file descriptors!";
// This should not be reached.
return false;
}
msg->header()->num_handles = msg->attached_handles_.Length();
msgh.msg_control = buf;
msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
cmsg = CMSG_FIRSTHDR(&msgh);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
for (unsigned i = 0; i < num_fds; ++i) {
reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] =
msg->attached_handles_[i].get();
}
msgh.msg_controllen = cmsg->cmsg_len;
msg->header()->num_handles = num_fds;
#if defined(OS_MACOSX)
msg->set_fd_cookie(++last_pending_fd_id_);
#endif
@@ -618,37 +632,14 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
size_t amt_to_write = 0;
// How much of this message have we written so far?
Pickle::BufferList::IterImpl iter = partial_write_->iter_;
auto handles = partial_write_->handles_;
Pickle::BufferList::IterImpl iter = partial_write_iter_.value();
size_t max_amt_to_write = iter.TotalBytesAvailable(msg->Buffers());
if (!handles.IsEmpty()) {
// We can only send at most kControlBufferMaxFds files per sendmsg call.
const size_t num_fds = std::min(handles.Length(), kControlBufferMaxFds);
// Populate the cmsg header for this call
msgh.msg_control = cmsgBuf;
msgh.msg_controllen = CMSG_LEN(sizeof(int) * num_fds);
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msgh);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = msgh.msg_controllen;
for (size_t i = 0; i < num_fds; ++i) {
reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] = handles[i].get();
}
// Update partial_write_ to record which handles were written.
auto remaining = handles.From(num_fds);
partial_write_->handles_ = remaining;
// Avoid writing one byte per remaining handle in excess of
// kControlBufferMaxFds. Each handle written will consume a minimum of 4
// bytes in the message (to store it's index), so we can depend on there
// being enough data to send every handle.
MOZ_ASSERT(max_amt_to_write > remaining.Length(),
"must be at least one byte in the message for each handle");
max_amt_to_write -= remaining.Length();
}
// Store the unwritten part of the first segment to write into the iovec.
iov[0].iov_base = const_cast<char*>(iter.Data());
iov[0].iov_len = iter.RemainingInSegment();
amt_to_write += iov[0].iov_len;
iter.Advance(msg->Buffers(), iov[0].iov_len);
iov_count++;
// Store remaining segments to write into iovec.
//
@@ -656,11 +647,9 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
// OS-dependent limits. Also, stop adding iovecs if we've already
// prepared to write at least the full buffer size.
while (!iter.Done() && iov_count < kMaxIOVecSize &&
PipeBufHasSpaceAfter(amt_to_write) &&
amt_to_write < max_amt_to_write) {
PipeBufHasSpaceAfter(amt_to_write)) {
char* data = iter.Data();
size_t size =
std::min(iter.RemainingInSegment(), max_amt_to_write - amt_to_write);
size_t size = iter.RemainingInSegment();
iov[iov_count].iov_base = data;
iov[iov_count].iov_len = size;
@@ -668,7 +657,6 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
amt_to_write += size;
iter.Advance(msg->Buffers(), size);
}
MOZ_ASSERT(amt_to_write <= max_amt_to_write);
const bool intentional_short_write = !iter.Done();
msgh.msg_iov = iov;
@@ -677,6 +665,14 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
ssize_t bytes_written =
HANDLE_EINTR(corrected_sendmsg(pipe_, &msgh, MSG_DONTWAIT));
#if !defined(OS_MACOSX)
// On OSX the attached_handles_ array gets cleared later, once we get the
// RECEIVED_FDS_MESSAGE_TYPE message.
if (bytes_written > 0) {
msg->attached_handles_.Clear();
}
#endif
if (bytes_written < 0) {
switch (errno) {
case EAGAIN:
@@ -722,10 +718,10 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
MOZ_DIAGNOSTIC_ASSERT(intentional_short_write ||
static_cast<size_t>(bytes_written) <
amt_to_write);
partial_write_->iter_.AdvanceAcrossSegments(msg->Buffers(),
bytes_written);
partial_write_iter_.ref().AdvanceAcrossSegments(msg->Buffers(),
bytes_written);
// We should not hit the end of the buffer.
MOZ_DIAGNOSTIC_ASSERT(!partial_write_->iter_.Done());
MOZ_DIAGNOSTIC_ASSERT(!partial_write_iter_.ref().Done());
}
// Tell libevent to call us back once things are unblocked.
@@ -736,17 +732,13 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
MessageLoopForIO::WATCH_WRITE, &write_watcher_, this);
return true;
} else {
partial_write_.reset();
partial_write_iter_.reset();
#if defined(OS_MACOSX)
if (!msg->attached_handles_.IsEmpty()) {
pending_fds_.push_back(PendingDescriptors{
msg->fd_cookie(), std::move(msg->attached_handles_)});
}
#else
if (bytes_written > 0) {
msg->attached_handles_.Clear();
}
#endif
// Message sent OK!
@@ -851,7 +843,7 @@ void Channel::ChannelImpl::OutputQueuePush(mozilla::UniquePtr<Message> msg) {
void Channel::ChannelImpl::OutputQueuePop() {
// Clear any reference to the front of output_queue_ before we destroy it.
partial_write_.reset();
partial_write_iter_.reset();
mozilla::UniquePtr<Message> message = output_queue_.Pop();
}

View File

@@ -100,11 +100,7 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
// If sending a message blocks then we use this iterator to keep track of
// where in the message we are. It gets reset when the message is finished
// sending.
struct PartialWrite {
Pickle::BufferList::IterImpl iter_;
mozilla::Span<const mozilla::UniqueFileHandle> handles_;
};
mozilla::Maybe<PartialWrite> partial_write_;
mozilla::Maybe<Pickle::BufferList::IterImpl> partial_write_iter_;
int server_listen_pipe_;
int pipe_;
@@ -124,19 +120,18 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
// The control message buffer will hold all of the file descriptors that will
// be read in during a single recvmsg call. Message::WriteFileDescriptor
// always writes one word of data for every file descriptor added to the
// message, and the number of file descriptors per recvmsg will not exceed
// kControlBufferMaxFds. This is based on the true maximum SCM_RIGHTS
// descriptor count, which is just over 250 on both Linux and macOS.
// message, and the number of file descriptors per message will not exceed
// MAX_DESCRIPTORS_PER_MESSAGE.
//
// This buffer also holds a control message header of size CMSG_SPACE(0)
// bytes. However, CMSG_SPACE is not a constant on Macs, so we can't use it
// here. Consequently, we pick a number here that is at least CMSG_SPACE(0) on
// all platforms. We assert at runtime, in Channel::ChannelImpl::Init, that
// it's big enough.
static constexpr size_t kControlBufferMaxFds = 200;
static constexpr size_t kControlBufferHeaderSize = 32;
static constexpr size_t kControlBufferSize =
kControlBufferMaxFds * sizeof(int) + kControlBufferHeaderSize;
IPC::Message::MAX_DESCRIPTORS_PER_MESSAGE * sizeof(int) +
kControlBufferHeaderSize;
// Large incoming messages that span multiple pipe buffers get built-up in the
// buffers of this message.

View File

@@ -93,8 +93,9 @@ class Message : public mojo::core::ports::UserMessage, public Pickle {
REPLY = 1,
};
// The hard limit of handles or file descriptors allowed in a single message.
static constexpr size_t MAX_DESCRIPTORS_PER_MESSAGE = 32767;
// Mac and Linux both limit the number of file descriptors per message to
// slightly more than 250.
enum { MAX_DESCRIPTORS_PER_MESSAGE = 200 };
class HeaderFlags {
friend class Message;

View File

@@ -1,15 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
namespace mozilla {
namespace _ipdltest {
[ParentImpl=virtual, ChildImpl=virtual]
async protocol PTestManyHandles {
child:
async ManyHandles(FileDescriptor[] descrs);
};
} // namespace _ipdltest
} // namespace mozilla

View File

@@ -1,72 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/_ipdltest/IPDLUnitTest.h"
#include "mozilla/_ipdltest/PTestManyHandlesChild.h"
#include "mozilla/_ipdltest/PTestManyHandlesParent.h"
using namespace mozilla::ipc;
namespace mozilla::_ipdltest {
class TestManyHandlesChild : public PTestManyHandlesChild {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestManyHandlesChild, override)
public:
IPCResult RecvManyHandles(nsTArray<FileDescriptor>&& aDescrs) override {
EXPECT_EQ(aDescrs.Length(), 500u);
for (int i = 0; i < static_cast<int>(aDescrs.Length()); ++i) {
UniqueFileHandle handle = aDescrs[i].TakePlatformHandle();
int value;
const int size = sizeof(value);
#ifdef XP_WIN
EXPECT_TRUE(::ReadFile(handle.get(), &value, size, nullptr, nullptr));
#else
EXPECT_EQ(read(handle.get(), &value, size), size);
#endif
EXPECT_EQ(value, i);
}
Close();
return IPC_OK();
}
private:
~TestManyHandlesChild() = default;
};
class TestManyHandlesParent : public PTestManyHandlesParent {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestManyHandlesParent, override)
private:
~TestManyHandlesParent() = default;
};
IPDL_TEST(TestManyHandles) {
nsTArray<FileDescriptor> descrs;
for (int i = 0; i < 500; ++i) {
const int size = sizeof(i);
UniqueFileHandle readPipe;
UniqueFileHandle writePipe;
#ifdef XP_WIN
ASSERT_TRUE(::CreatePipe(getter_Transfers(readPipe),
getter_Transfers(writePipe), nullptr, size));
ASSERT_TRUE(::WriteFile(writePipe.get(), &i, size, nullptr, nullptr));
#else
int fds[2];
ASSERT_EQ(pipe(fds), 0);
readPipe.reset(fds[0]);
writePipe.reset(fds[1]);
ASSERT_EQ(write(writePipe.get(), &i, size), size);
#endif
descrs.AppendElement(FileDescriptor(std::move(readPipe)));
}
bool ok = mActor->SendManyHandles(descrs);
ASSERT_TRUE(ok);
}
} // namespace mozilla::_ipdltest

View File

@@ -17,13 +17,11 @@ EXPORTS.mozilla._ipdltest += [
SOURCES += [
"IPDLUnitTest.cpp",
"TestBasic.cpp",
"TestManyHandles.cpp",
]
IPDL_SOURCES += [
"PIPDLUnitTest.ipdl",
"PTestBasic.ipdl",
"PTestManyHandles.ipdl",
]
include("/ipc/chromium/chromium-config.mozbuild")