| Index: handler/mac/exception_handler_server.cc
|
| diff --git a/handler/mac/exception_handler_server.cc b/handler/mac/exception_handler_server.cc
|
| index 19038293bf104be39b48310cfa139efe57eaaadc..845b34dd1b326e4bfc400cd97dcd1a3bcbcd5be4 100644
|
| --- a/handler/mac/exception_handler_server.cc
|
| +++ b/handler/mac/exception_handler_server.cc
|
| @@ -14,12 +14,7 @@
|
|
|
| #include "handler/mac/exception_handler_server.h"
|
|
|
| -#include <signal.h>
|
| -
|
| -#include "base/auto_reset.h"
|
| #include "base/logging.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/scoped_generic.h"
|
| #include "base/mac/mach_logging.h"
|
| #include "util/mach/composite_mach_message_server.h"
|
| #include "util/mach/mach_extensions.h"
|
| @@ -31,58 +26,12 @@ namespace crashpad {
|
|
|
| namespace {
|
|
|
| -struct ResetSIGTERMTraits {
|
| - static struct sigaction* InvalidValue() {
|
| - return nullptr;
|
| - }
|
| -
|
| - static void Free(struct sigaction* sa) {
|
| - int rv = sigaction(SIGTERM, sa, nullptr);
|
| - PLOG_IF(ERROR, rv != 0) << "sigaction";
|
| - }
|
| -};
|
| -using ScopedResetSIGTERM =
|
| - base::ScopedGeneric<struct sigaction*, ResetSIGTERMTraits>;
|
| -
|
| -mach_port_t g_signal_notify_port;
|
| -
|
| -// This signal handler is only operative when being run from launchd. It causes
|
| -// the exception handler server to stop running by sending it a synthesized
|
| -// no-senders notification.
|
| -void HandleSIGTERM(int sig, siginfo_t* siginfo, void* context) {
|
| - DCHECK(g_signal_notify_port);
|
| -
|
| - // mach_no_senders_notification_t defines the receive side of this structure,
|
| - // with a trailer element that’s undesirable for the send side.
|
| - struct {
|
| - mach_msg_header_t header;
|
| - NDR_record_t ndr;
|
| - mach_msg_type_number_t mscount;
|
| - } no_senders_notification = {};
|
| - no_senders_notification.header.msgh_bits =
|
| - MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND_ONCE, 0);
|
| - no_senders_notification.header.msgh_size = sizeof(no_senders_notification);
|
| - no_senders_notification.header.msgh_remote_port = g_signal_notify_port;
|
| - no_senders_notification.header.msgh_local_port = MACH_PORT_NULL;
|
| - no_senders_notification.header.msgh_id = MACH_NOTIFY_NO_SENDERS;
|
| - no_senders_notification.ndr = NDR_record;
|
| - no_senders_notification.mscount = 0;
|
| -
|
| - kern_return_t kr = mach_msg(&no_senders_notification.header,
|
| - MACH_SEND_MSG,
|
| - sizeof(no_senders_notification),
|
| - 0,
|
| - MACH_PORT_NULL,
|
| - MACH_MSG_TIMEOUT_NONE,
|
| - MACH_PORT_NULL);
|
| - MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_msg";
|
| -}
|
| -
|
| class ExceptionHandlerServerRun : public UniversalMachExcServer::Interface,
|
| public NotifyServer::DefaultInterface {
|
| public:
|
| ExceptionHandlerServerRun(
|
| mach_port_t exception_port,
|
| + mach_port_t notify_port,
|
| bool launchd,
|
| UniversalMachExcServer::Interface* exception_interface)
|
| : UniversalMachExcServer::Interface(),
|
| @@ -92,11 +41,9 @@ class ExceptionHandlerServerRun : public UniversalMachExcServer::Interface,
|
| composite_mach_message_server_(),
|
| exception_interface_(exception_interface),
|
| exception_port_(exception_port),
|
| - notify_port_(NewMachPort(MACH_PORT_RIGHT_RECEIVE)),
|
| + notify_port_(notify_port),
|
| running_(true),
|
| launchd_(launchd) {
|
| - CHECK(notify_port_.is_valid());
|
| -
|
| composite_mach_message_server_.AddHandler(&mach_exc_server_);
|
| composite_mach_message_server_.AddHandler(¬ify_server_);
|
| }
|
| @@ -108,9 +55,6 @@ class ExceptionHandlerServerRun : public UniversalMachExcServer::Interface,
|
| DCHECK(running_);
|
|
|
| kern_return_t kr;
|
| - scoped_ptr<base::AutoReset<mach_port_t>> reset_signal_notify_port;
|
| - struct sigaction old_sa;
|
| - ScopedResetSIGTERM reset_sigterm;
|
| if (!launchd_) {
|
| // Request that a no-senders notification for exception_port_ be sent to
|
| // notify_port_.
|
| @@ -119,33 +63,11 @@ class ExceptionHandlerServerRun : public UniversalMachExcServer::Interface,
|
| exception_port_,
|
| MACH_NOTIFY_NO_SENDERS,
|
| 0,
|
| - notify_port_.get(),
|
| + notify_port_,
|
| MACH_MSG_TYPE_MAKE_SEND_ONCE,
|
| &previous);
|
| MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_request_notification";
|
| -
|
| - if (previous != MACH_PORT_NULL) {
|
| - kr = mach_port_deallocate(mach_task_self(), previous);
|
| - MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_deallocate";
|
| - }
|
| - } else {
|
| - // A real no-senders notification would never be triggered, because
|
| - // launchd maintains a send right to the service. When launchd wants the
|
| - // job to exit, it will send a SIGTERM. See launchd.plist(5).
|
| - //
|
| - // Set up a SIGTERM handler that will cause Run() to return (incidentally,
|
| - // by sending a synthetic no-senders notification).
|
| - struct sigaction sa = {};
|
| - sigemptyset(&sa.sa_mask);
|
| - sa.sa_flags = SA_SIGINFO;
|
| - sa.sa_sigaction = HandleSIGTERM;
|
| - int rv = sigaction(SIGTERM, &sa, &old_sa);
|
| - PCHECK(rv == 0) << "sigaction";
|
| - reset_sigterm.reset(&old_sa);
|
| -
|
| - DCHECK(!g_signal_notify_port);
|
| - reset_signal_notify_port.reset(new base::AutoReset<mach_port_t>(
|
| - &g_signal_notify_port, notify_port_.get()));
|
| + base::mac::ScopedMachSendRight previous_owner(previous);
|
| }
|
|
|
| // A single CompositeMachMessageServer will dispatch both exception messages
|
| @@ -165,7 +87,7 @@ class ExceptionHandlerServerRun : public UniversalMachExcServer::Interface,
|
| MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_insert_member";
|
|
|
| kr = mach_port_insert_member(
|
| - mach_task_self(), notify_port_.get(), server_port_set.get());
|
| + mach_task_self(), notify_port_, server_port_set.get());
|
| MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_insert_member";
|
|
|
| // Run the server in kOneShot mode so that running_ can be reevaluated after
|
| @@ -249,7 +171,7 @@ class ExceptionHandlerServerRun : public UniversalMachExcServer::Interface,
|
| CompositeMachMessageServer composite_mach_message_server_;
|
| UniversalMachExcServer::Interface* exception_interface_; // weak
|
| mach_port_t exception_port_; // weak
|
| - base::mac::ScopedMachReceiveRight notify_port_;
|
| + mach_port_t notify_port_; // weak
|
| bool running_;
|
| bool launchd_;
|
|
|
| @@ -262,8 +184,10 @@ ExceptionHandlerServer::ExceptionHandlerServer(
|
| base::mac::ScopedMachReceiveRight receive_port,
|
| bool launchd)
|
| : receive_port_(receive_port.Pass()),
|
| + notify_port_(NewMachPort(MACH_PORT_RIGHT_RECEIVE)),
|
| launchd_(launchd) {
|
| CHECK(receive_port_.is_valid());
|
| + CHECK(notify_port_.is_valid());
|
| }
|
|
|
| ExceptionHandlerServer::~ExceptionHandlerServer() {
|
| @@ -272,8 +196,38 @@ ExceptionHandlerServer::~ExceptionHandlerServer() {
|
| void ExceptionHandlerServer::Run(
|
| UniversalMachExcServer::Interface* exception_interface) {
|
| ExceptionHandlerServerRun run(
|
| - receive_port_.get(), launchd_, exception_interface);
|
| + receive_port_.get(), notify_port_.get(), launchd_, exception_interface);
|
| run.Run();
|
| }
|
|
|
| +void ExceptionHandlerServer::Stop() {
|
| + // Cause the exception handler server to stop running by sending it a
|
| + // synthesized no-senders notification.
|
| + //
|
| + // mach_no_senders_notification_t defines the receive side of this structure,
|
| + // with a trailer element that’s undesirable for the send side.
|
| + struct {
|
| + mach_msg_header_t header;
|
| + NDR_record_t ndr;
|
| + mach_msg_type_number_t mscount;
|
| + } no_senders_notification = {};
|
| + no_senders_notification.header.msgh_bits =
|
| + MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND_ONCE, 0);
|
| + no_senders_notification.header.msgh_size = sizeof(no_senders_notification);
|
| + no_senders_notification.header.msgh_remote_port = notify_port_.get();
|
| + no_senders_notification.header.msgh_local_port = MACH_PORT_NULL;
|
| + no_senders_notification.header.msgh_id = MACH_NOTIFY_NO_SENDERS;
|
| + no_senders_notification.ndr = NDR_record;
|
| + no_senders_notification.mscount = 0;
|
| +
|
| + kern_return_t kr = mach_msg(&no_senders_notification.header,
|
| + MACH_SEND_MSG,
|
| + sizeof(no_senders_notification),
|
| + 0,
|
| + MACH_PORT_NULL,
|
| + MACH_MSG_TIMEOUT_NONE,
|
| + MACH_PORT_NULL);
|
| + MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_msg";
|
| +}
|
| +
|
| } // namespace crashpad
|
|
|