Add ScopedForbidReturn and its test.

Use ScopedForbidReturn in ProcessReader::InitializeThreads().

TEST=util_test ScopedForbidReturn*.*
R=rsesek@chromium.org

Review URL: https://codereview.chromium.org/493203005
This commit is contained in:
Mark Mentovai 2014-08-26 16:50:08 -04:00
parent 8256f9fc23
commit 0cc86a24f9
5 changed files with 147 additions and 0 deletions

View File

@ -24,6 +24,7 @@
#include "base/mac/mach_logging.h"
#include "base/mac/scoped_mach_port.h"
#include "base/mac/scoped_mach_vm.h"
#include "util/misc/scoped_forbid_return.h"
namespace {
@ -221,6 +222,7 @@ void ProcessReader::InitializeThreads() {
// by anything until theyre added to |threads_| by the loop below. Any early
// return (or exception) that happens between here and the completion of the
// loop below will leak thread port send rights.
ScopedForbidReturn threads_need_owners;
base::mac::ScopedMachVM threads_vm(
reinterpret_cast<vm_address_t>(threads),
@ -340,6 +342,8 @@ void ProcessReader::InitializeThreads() {
threads_.push_back(thread);
}
threads_need_owners.Disarm();
}
void ProcessReader::InitializeModules() {

View File

@ -0,0 +1,27 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "util/misc/scoped_forbid_return.h"
#include "base/logging.h"
namespace crashpad {
ScopedForbidReturn::~ScopedForbidReturn() {
if (armed_) {
LOG(FATAL) << "attempt to exit scope forbidden";
}
}
} // namespace crashpad

View File

@ -0,0 +1,54 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_UTIL_MISC_SCOPED_FORBID_RETURN_H_
#define CRASHPAD_UTIL_MISC_SCOPED_FORBID_RETURN_H_
#include "base/basictypes.h"
namespace crashpad {
//! \brief Asserts that a scope must not be exited while unsafe.
//!
//! An object of this class has two states: armed and disarmed. A disarmed
//! object is a harmless no-op. An armed object will abort execution upon
//! destruction. Newly-constructed objects are armed by default.
//!
//! These objects may be used to assert that a scope not be exited while it is
//! unsafe to do so. If it ever becomes safe to leave such a scope, an object
//! can be disarmed.
class ScopedForbidReturn {
public:
ScopedForbidReturn() : armed_(true) {}
~ScopedForbidReturn();
//! \brief Arms the object so that it will abort execution when destroyed.
//!
//! The most recent call to Arm() or Disarm() sets the state of the object.
void Arm() { armed_ = true; }
//! \brief Arms the object so that it will abort execution when destroyed.
//!
//! The most recent call to Arm() or Disarm() sets the state of the object.
void Disarm() { armed_ = false; }
private:
bool armed_;
DISALLOW_COPY_AND_ASSIGN(ScopedForbidReturn);
};
} // namespace crashpad
#endif // CRASHPAD_UTIL_MISC_SCOPED_FORBID_RETURN_H_

View File

@ -0,0 +1,59 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "util/misc/scoped_forbid_return.h"
#include "gtest/gtest.h"
namespace {
using namespace crashpad;
enum ForbidReturnType {
kForbidReturnDefault = 0,
kForbidReturnArmed,
kForbidReturnDisarmed,
};
void ScopedForbidReturnHelper(ForbidReturnType type) {
ScopedForbidReturn forbid_return;
switch (type) {
case kForbidReturnDefault:
break;
case kForbidReturnArmed:
forbid_return.Arm();
break;
case kForbidReturnDisarmed:
forbid_return.Disarm();
break;
}
}
const char kForbiddenMessage[] = "attempt to exit scope forbidden";
TEST(ScopedForbidReturnDeathTest, Default) {
ASSERT_DEATH(ScopedForbidReturnHelper(kForbidReturnDefault),
kForbiddenMessage);
}
TEST(ScopedForbidReturnDeathTest, Armed) {
ASSERT_DEATH(ScopedForbidReturnHelper(kForbidReturnArmed), kForbiddenMessage);
}
TEST(ScopedForbidReturn, Disarmed) {
ScopedForbidReturnHelper(kForbidReturnDisarmed);
}
} // namespace

View File

@ -47,6 +47,8 @@
'misc/initialization_state.h',
'misc/initialization_state_dcheck.cc',
'misc/initialization_state_dcheck.h',
'misc/scoped_forbid_return.cc',
'misc/scoped_forbid_return.h',
'misc/uuid.cc',
'misc/uuid.h',
'numeric/checked_range.h',
@ -111,6 +113,7 @@
'mach/task_memory_test.cc',
'misc/initialization_state_dcheck_test.cc',
'misc/initialization_state_test.cc',
'misc/scoped_forbid_return_test.cc',
'misc/uuid_test.cc',
'numeric/checked_range_test.cc',
'numeric/in_range_cast_test.cc',