Bug 1479960 - Convert MemMapSnapshot to use frozen shared memory. r=kmag

Depends on D26745

Differential Revision: https://phabricator.services.mozilla.com/D26746

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jed Davis 2019-06-20 22:40:38 +00:00
Родитель 406448ffe1
Коммит 67a30a842d
2 изменённых файлов: 23 добавлений и 100 удалений

Просмотреть файл

@ -6,109 +6,41 @@
#include "MemMapSnapshot.h"
#include "base/eintr_wrapper.h"
#include "base/file_util.h"
#include "mozilla/AutoMemMap.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "nsIFile.h"
#ifdef XP_UNIX
# include <sys/stat.h>
#endif
namespace mozilla {
using loader::AutoMemMap;
namespace ipc {
Result<Ok, nsresult> MemMapSnapshot::Init(size_t aSize) {
MOZ_ASSERT(!mInitialized);
MOZ_TRY(Create(aSize));
if (NS_WARN_IF(!mMem.CreateFreezeable(aSize))) {
return Err(NS_ERROR_FAILURE);
}
if (NS_WARN_IF(!mMem.Map(aSize))) {
return Err(NS_ERROR_FAILURE);
}
mInitialized = true;
return Ok();
}
Result<Ok, nsresult> MemMapSnapshot::Finalize(AutoMemMap& aMem) {
Result<Ok, nsresult> MemMapSnapshot::Finalize(loader::AutoMemMap& aMem) {
MOZ_ASSERT(mInitialized);
MOZ_TRY(Freeze(aMem));
if (NS_WARN_IF(!mMem.Freeze())) {
return Err(NS_ERROR_FAILURE);
}
// TakeHandle resets mMem, so call max_size first.
size_t size = mMem.max_size();
FileDescriptor memHandle(mMem.TakeHandle());
MOZ_TRY(aMem.initWithHandle(memHandle, size));
mInitialized = false;
return Ok();
}
#if defined(XP_WIN)
Result<Ok, nsresult> MemMapSnapshot::Create(size_t aSize) {
HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr,
PAGE_READWRITE, 0, DWORD(aSize), nullptr);
if (!handle) {
return Err(NS_ERROR_FAILURE);
}
mFile.emplace(handle);
return mMem.initWithHandle(mFile.ref(), aSize, PR_PROT_READWRITE);
}
Result<Ok, nsresult> MemMapSnapshot::Freeze(AutoMemMap& aMem) {
auto orig = mFile.ref().ClonePlatformHandle();
mFile.reset();
HANDLE handle;
if (!::DuplicateHandle(
GetCurrentProcess(), orig.release(), GetCurrentProcess(), &handle,
GENERIC_READ | FILE_MAP_READ, false, DUPLICATE_CLOSE_SOURCE)) {
return Err(NS_ERROR_FAILURE);
}
return aMem.initWithHandle(FileDescriptor(handle), mMem.size());
}
#elif defined(XP_UNIX)
Result<Ok, nsresult> MemMapSnapshot::Create(size_t aSize) {
FilePath path;
ScopedCloseFile fd(file_util::CreateAndOpenTemporaryShmemFile(&path));
if (!fd) {
return Err(NS_ERROR_FAILURE);
}
if (HANDLE_EINTR(ftruncate(fileno(fd), aSize)) != 0) {
return Err(NS_ERROR_FAILURE);
}
MOZ_TRY(mMem.init(FILEToFileDescriptor(fd), PR_PROT_READWRITE));
mPath.Assign(path.value().data(), path.value().length());
return Ok();
}
Result<Ok, nsresult> MemMapSnapshot::Freeze(AutoMemMap& aMem) {
// Delete the shm file after we're done here, whether we succeed or not. The
// open file descriptor will keep it alive until all remaining references
// are closed, at which point it will be automatically freed.
auto cleanup = MakeScopeExit([&]() { PR_Delete(mPath.get()); });
// Make the shm file readonly. This doesn't make a difference in practice,
// since we open and share a read-only file descriptor, and then delete the
// file. But it doesn't hurt, either.
chmod(mPath.get(), 0400);
nsCOMPtr<nsIFile> file;
MOZ_TRY(NS_NewNativeLocalFile(mPath, /* followLinks = */ false,
getter_AddRefs(file)));
return aMem.init(file);
}
#else
# error "Unsupported build configuration"
#endif
} // namespace ipc
} // namespace mozilla

Просмотреть файл

@ -7,16 +7,17 @@
#ifndef dom_ipc_MemMapSnapshot_h
#define dom_ipc_MemMapSnapshot_h
#include "mozilla/AutoMemMap.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/Result.h"
#ifdef XP_WIN
# include "mozilla/ipc/FileDescriptor.h"
#endif
#include "base/shared_memory.h"
namespace mozilla {
namespace loader {
class AutoMemMap;
}
namespace ipc {
/**
@ -35,25 +36,15 @@ class MOZ_RAII MemMapSnapshot {
Result<Ok, nsresult> Init(size_t aSize);
Result<Ok, nsresult> Finalize(loader::AutoMemMap& aMap);
template <typename T = void>
template <typename T>
RangedPtr<T> Get() {
MOZ_ASSERT(mInitialized);
return mMem.get<T>();
return {static_cast<T*>(mMem.memory()), mMem.max_size() / sizeof(T)};
}
private:
Result<Ok, nsresult> Create(size_t aSize);
Result<Ok, nsresult> Freeze(loader::AutoMemMap& aMem);
loader::AutoMemMap mMem;
base::SharedMemory mMem;
bool mInitialized = false;
#ifdef XP_WIN
Maybe<FileDescriptor> mFile;
#else
nsCString mPath;
#endif
};
} // namespace ipc