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 |