зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
406448ffe1
Коммит
67a30a842d
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче