// Copyright 2017 The Crashpad Authors
//
// 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_TEST_MAC_EXCEPTION_SWALLOWER_H_
#define CRASHPAD_TEST_MAC_EXCEPTION_SWALLOWER_H_
#include <memory>
namespace crashpad {
namespace test {
//! \brief Swallows `EXC_CRASH` and `EXC_CORPSE_NOTIFY` exceptions in test child
//! processes.
//!
//! This class is intended to be used by test code that crashes intentionally.
//!
//! On macOS, the system’s crash reporter normally saves crash reports for all
//! crashes in test code, by virtue of being set as the `EXC_CRASH` or
//! `EXC_CORPSE_NOTIFY` handler. This litters the user’s
//! `~/Library/Logs/DiagnosticReports` directory and can be time-consuming.
//! Reports generated for code that crashes intentionally have no value, and
//! many Crashpad tests do crash intentionally.
//!
//! Instantiate an ExceptionSwallower object in a parent test process (a process
//! where `TEST()`, `TEST_F()`, and `TEST_P()` execute) to create an exception
//! swallower server running on a dedicated thread. A service mapping for this
//! server will be published with the bootstrap server and made available in the
//! `CRASHPAD_EXCEPTION_SWALLOWER_SERVICE` environment variable. In a child
//! process, call SwallowExceptions() to look up this service and set it as the
//! `EXC_CRASH` and `EXC_CORPSE_NOTIFY` handler. When these exceptions are
//! raised in the child process, they’ll be handled by the exception swallower
//! server, which performs no action but reports that exceptions were
//! successfully handled so that the system’s crash reporter, ReportCrash, will
//! not be invoked.
//!
//! At most one ExceptionSwallower may be instantiated in a process at a time.
//! If `CRASHPAD_EXCEPTION_SWALLOWER_SERVICE` is already set, ExceptionSwallower
//! leaves it in place and takes no additional action.
//!
//! Crashpad’s ASSERT_DEATH_CRASH(), EXPECT_DEATH_CRASH(), ASSERT_DEATH_CHECK(),
//! and EXPECT_DEATH_CHECK() macros make use of this class on macOS, as does the
//! Multiprocess test interface.
class ExceptionSwallower {
public:
ExceptionSwallower();
ExceptionSwallower(const ExceptionSwallower&) = delete;
ExceptionSwallower& operator=(const ExceptionSwallower&) = delete;
~ExceptionSwallower();
//! \brief In a test child process, arranges to swallow `EXC_CRASH` and
//! `EXC_CORPSE_NOTIFY` exceptions.
//!
//! This must be called in a test child process. It must not be called from a
//! parent test process directly. Parent test processes are those that execute
//! `TEST()`, `TEST_F()`, and `TEST_P()`. Test child processes execute
//! ASSERT_DEATH_CRASH(), EXPECT_DEATH_CRASH(), ASSERT_DEATH_CHECK(),
//! EXPECT_DEATH_CHECK(), and Multiprocess::RunChild().
//!
//! It is an error to call this in a test child process without having first
//! instantiated an ExceptionSwallower object in a parent test project. It is
//! also an error to call this in a parent test process.
static void SwallowExceptions();
private:
class ExceptionSwallowerThread;
std::unique_ptr<ExceptionSwallowerThread> exception_swallower_thread_;
};
} // namespace test
} // namespace crashpad
#endif // CRASHPAD_TEST_MAC_EXCEPTION_SWALLOWER_H_