Bug 1341496 - Part 3: Make CrossProcessSemaphore allocation fallible. r=billm

--HG--
extra : rebase_source : 318d2c835675547acf667ecfb20bb595ea86e59f
This commit is contained in:
Matt Woodrow 2017-04-19 15:39:11 +12:00
Родитель 227b55240c
Коммит d2f04fbaa8
5 изменённых файлов: 87 добавлений и 56 удалений

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

@ -1439,10 +1439,10 @@ class CrossProcessSemaphoreReadLock : public TextureReadLock
{
public:
CrossProcessSemaphoreReadLock()
: mSemaphore("TextureReadLock", 1)
: mSemaphore(CrossProcessSemaphore::Create("TextureReadLock", 1))
{}
explicit CrossProcessSemaphoreReadLock(CrossProcessSemaphoreHandle aHandle)
: mSemaphore(aHandle)
: mSemaphore(CrossProcessSemaphore::Create(aHandle))
{}
virtual bool ReadLock() override
@ -1450,30 +1450,30 @@ public:
if (!IsValid()) {
return false;
}
return mSemaphore.Wait();
return mSemaphore->Wait();
}
virtual bool TryReadLock(TimeDuration aTimeout) override
{
if (!IsValid()) {
return false;
}
return mSemaphore.Wait(Some(aTimeout));
return mSemaphore->Wait(Some(aTimeout));
}
virtual int32_t ReadUnlock() override
{
if (!IsValid()) {
return 1;
}
mSemaphore.Signal();
mSemaphore->Signal();
return 1;
}
virtual bool IsValid() const override { return true; }
virtual bool IsValid() const override { return !!mSemaphore; }
virtual bool Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther) override;
virtual LockType GetType() override { return TYPE_CROSS_PROCESS_SEMAPHORE; }
CrossProcessSemaphore mSemaphore;
UniquePtr<CrossProcessSemaphore> mSemaphore;
};
// static
@ -1656,7 +1656,7 @@ bool
CrossProcessSemaphoreReadLock::Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther)
{
if (IsValid()) {
aOutput = ReadLockDescriptor(CrossProcessSemaphoreDescriptor(mSemaphore.ShareToProcess(aOther)));
aOutput = ReadLockDescriptor(CrossProcessSemaphoreDescriptor(mSemaphore->ShareToProcess(aOther)));
return true;
} else {
return false;

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

@ -45,13 +45,14 @@ public:
* CrossProcessSemaphore
* @param name A name which can reference this lock (currently unused)
**/
explicit CrossProcessSemaphore(const char* aName, uint32_t aInitialValue);
static CrossProcessSemaphore* Create(const char* aName, uint32_t aInitialValue);
/**
* CrossProcessSemaphore
* @param handle A handle of an existing cross process semaphore that can be
* opened.
*/
explicit CrossProcessSemaphore(CrossProcessSemaphoreHandle aHandle);
static CrossProcessSemaphore* Create(CrossProcessSemaphoreHandle aHandle);
~CrossProcessSemaphore();
@ -85,6 +86,8 @@ private:
CrossProcessSemaphore &operator=(const CrossProcessSemaphore&);
#if defined(OS_WIN)
explicit CrossProcessSemaphore(HANDLE aSemaphore);
HANDLE mSemaphore;
#elif !defined(OS_MACOSX)
RefPtr<mozilla::ipc::SharedMemoryBasic> mSharedBuffer;

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

@ -26,73 +26,84 @@ struct SemaphoreData {
namespace mozilla {
CrossProcessSemaphore::CrossProcessSemaphore(const char*, uint32_t aInitialValue)
: mSemaphore(nullptr)
, mRefCount(nullptr)
/* static */ CrossProcessSemaphore*
CrossProcessSemaphore::Create(const char*, uint32_t aInitialValue)
{
mSharedBuffer = new ipc::SharedMemoryBasic;
if (!mSharedBuffer->Create(sizeof(SemaphoreData))) {
MOZ_CRASH();
RefPtr<ipc::SharedMemoryBasic> sharedBuffer = new ipc::SharedMemoryBasic;
if (!sharedBuffer->Create(sizeof(SemaphoreData))) {
return nullptr;
}
if (!mSharedBuffer->Map(sizeof(SemaphoreData))) {
MOZ_CRASH();
if (!sharedBuffer->Map(sizeof(SemaphoreData))) {
return nullptr;
}
SemaphoreData* data = static_cast<SemaphoreData*>(mSharedBuffer->memory());
SemaphoreData* data = static_cast<SemaphoreData*>(sharedBuffer->memory());
if (!data) {
MOZ_CRASH();
return nullptr;
}
if (sem_init(&data->mSemaphore, 1, aInitialValue)) {
return nullptr;
}
CrossProcessSemaphore* sem = new CrossProcessSemaphore;
sem->mSharedBuffer = sharedBuffer;
sem->mSemaphore = &data->mSemaphore;
sem->mRefCount = &data->mRefCount;
*sem->mRefCount = 1;
data->mInitialValue = aInitialValue;
mSemaphore = &data->mSemaphore;
mRefCount = &data->mRefCount;
*mRefCount = 1;
if (sem_init(mSemaphore, 1, data->mInitialValue)) {
MOZ_CRASH();
}
MOZ_COUNT_CTOR(CrossProcessSemaphore);
return sem;
}
CrossProcessSemaphore::CrossProcessSemaphore(CrossProcessSemaphoreHandle aHandle)
: mSemaphore(nullptr)
, mRefCount(nullptr)
/* static */ CrossProcessSemaphore*
CrossProcessSemaphore::Create(CrossProcessSemaphoreHandle aHandle)
{
mSharedBuffer = new ipc::SharedMemoryBasic;
RefPtr<ipc::SharedMemoryBasic> sharedBuffer = new ipc::SharedMemoryBasic;
if (!mSharedBuffer->IsHandleValid(aHandle)) {
MOZ_CRASH();
if (!sharedBuffer->IsHandleValid(aHandle)) {
return nullptr;
}
if (!mSharedBuffer->SetHandle(aHandle, ipc::SharedMemory::RightsReadWrite)) {
MOZ_CRASH();
if (!sharedBuffer->SetHandle(aHandle, ipc::SharedMemory::RightsReadWrite)) {
return nullptr;
}
if (!mSharedBuffer->Map(sizeof(SemaphoreData))) {
MOZ_CRASH();
if (!sharedBuffer->Map(sizeof(SemaphoreData))) {
return nullptr;
}
SemaphoreData* data = static_cast<SemaphoreData*>(mSharedBuffer->memory());
SemaphoreData* data = static_cast<SemaphoreData*>(sharedBuffer->memory());
if (!data) {
MOZ_CRASH();
return nullptr;
}
mSemaphore = &data->mSemaphore;
mRefCount = &data->mRefCount;
int32_t oldCount = (*mRefCount)++;
int32_t oldCount = data->mRefCount++;
if (oldCount == 0) {
// The other side has already let go of their CrossProcessSemaphore, so now
// mSemaphore is garbage. We need to re-initialize it.
if (sem_init(mSemaphore, 1, data->mInitialValue)) {
MOZ_CRASH();
if (sem_init(&data->mSemaphore, 1, data->mInitialValue)) {
data->mRefCount--;
return nullptr;
}
}
CrossProcessSemaphore* sem = new CrossProcessSemaphore;
sem->mSharedBuffer = sharedBuffer;
sem->mSemaphore = &data->mSemaphore;
sem->mRefCount = &data->mRefCount;
return sem;
}
CrossProcessSemaphore::CrossProcessSemaphore()
: mSemaphore(nullptr)
, mRefCount(nullptr)
{
MOZ_COUNT_CTOR(CrossProcessSemaphore);
}

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

@ -10,14 +10,23 @@
namespace mozilla {
CrossProcessSemaphore::CrossProcessSemaphore(const char*, uint32_t)
/* static */ CrossProcessSemaphore*
CrossProcessSemaphore::Create(const char*, uint32_t)
{
MOZ_CRASH("Cross-process semaphores not allowed on this platform.");
return nullptr;
}
CrossProcessSemaphore::CrossProcessSemaphore(CrossProcessSemaphoreHandle)
/* static */ CrossProcessSemaphore*
CrossProcessSemaphore::Create(CrossProcessSemaphoreHandle)
{
MOZ_CRASH("Cross-process semaphores not allowed on this platform.");
return nullptr;
}
CrossProcessSemaphore::CrossProcessSemaphore()
{
MOZ_CRASH("Cross-process semaphores not allowed on this platform - woah! We should've aborted by now!");
}
CrossProcessSemaphore::~CrossProcessSemaphore()

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

@ -17,25 +17,33 @@ using base::ProcessHandle;
namespace mozilla {
CrossProcessSemaphore::CrossProcessSemaphore(const char*, uint32_t aInitialValue)
/* static */ CrossProcessSemaphore*
CrossProcessSemaphore::Create(const char*, uint32_t aInitialValue)
{
// We explicitly share this using DuplicateHandle, we do -not- want this to
// be inherited by child processes by default! So no security attributes are
// given.
mSemaphore = ::CreateSemaphoreA(nullptr, aInitialValue, 0x7fffffff, nullptr);
if (!mSemaphore) {
MOZ_CRASH("This shouldn't happen - failed to create semaphore!");
HANDLE semaphore = ::CreateSemaphoreA(nullptr, aInitialValue, 0x7fffffff, nullptr);
if (!semaphore) {
return nullptr;
}
MOZ_COUNT_CTOR(CrossProcessSemaphore);
return new CrossProcessSemaphore(semaphore);
}
CrossProcessSemaphore::CrossProcessSemaphore(CrossProcessSemaphoreHandle aHandle)
/* static */ CrossProcessSemaphore*
CrossProcessSemaphore::Create(CrossProcessSemaphoreHandle aHandle)
{
DWORD flags;
if (!::GetHandleInformation(aHandle, &flags)) {
MOZ_CRASH("Attempt to construct a semaphore from an invalid handle!");
return nullptr;
}
mSemaphore = aHandle;
return new CrossProcessSemaphore(aHandle);
}
CrossProcessSemaphore::CrossProcessSemaphore(HANDLE aSemaphore)
: mSemaphore(aSemaphore)
{
MOZ_COUNT_CTOR(CrossProcessSemaphore);
}