mirror of
https://github.com/chromium/crashpad.git
synced 2025-01-14 09:17:57 +08:00
MachMessageServer: eliminate argument redundancy.
MachMessageServer::Run()’s distinct |nonblocking| parameter is removed. The information it formerly conveyed is now implied by the |timeout_ms| parameter, which can accept two special values, kMachMessageTimeoutNonblocking and kMachMessageTimeoutWaitIndefinitely. TEST=client_test, snapshot_test, util_test R=rsesek@chromium.org Review URL: https://codereview.chromium.org/777993002
This commit is contained in:
parent
22b2f0cad7
commit
c874958fd0
@ -25,6 +25,7 @@
|
||||
#include "util/mach/exception_behaviors.h"
|
||||
#include "util/mach/exception_ports.h"
|
||||
#include "util/mach/mach_extensions.h"
|
||||
#include "util/mach/mach_message.h"
|
||||
#include "util/mach/mach_message_server.h"
|
||||
#include "util/mach/symbolic_constants_mach.h"
|
||||
#include "util/test/mac/mach_errors.h"
|
||||
@ -251,9 +252,8 @@ class TestSimulateCrashMac final : public MachMultiprocess,
|
||||
LocalPort(),
|
||||
MACH_MSG_OPTION_NONE,
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kBlocking,
|
||||
MachMessageServer::kReceiveLargeError,
|
||||
MACH_MSG_TIMEOUT_NONE);
|
||||
kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(MACH_MSG_SUCCESS, mr)
|
||||
<< MachErrorMessage(mr, "MachMessageServer::Run");
|
||||
}
|
||||
@ -263,9 +263,8 @@ class TestSimulateCrashMac final : public MachMultiprocess,
|
||||
LocalPort(),
|
||||
MACH_MSG_OPTION_NONE,
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kBlocking,
|
||||
MachMessageServer::kReceiveLargeError,
|
||||
MACH_MSG_TIMEOUT_NONE);
|
||||
kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(MACH_MSG_SUCCESS, mr)
|
||||
<< MachErrorMessage(mr, "MachMessageServer::Run");
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "util/mac/mac_util.h"
|
||||
#include "util/mach/exc_server_variants.h"
|
||||
#include "util/mach/exception_ports.h"
|
||||
#include "util/mach/mach_message.h"
|
||||
#include "util/mach/mach_message_server.h"
|
||||
#include "util/test/errors.h"
|
||||
#include "util/test/mac/mach_errors.h"
|
||||
@ -227,9 +228,8 @@ class TestMachOImageAnnotationsReader final
|
||||
LocalPort(),
|
||||
MACH_MSG_OPTION_NONE,
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kBlocking,
|
||||
MachMessageServer::kReceiveLargeError,
|
||||
MACH_MSG_TIMEOUT_NONE);
|
||||
kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(MACH_MSG_SUCCESS, mr)
|
||||
<< MachErrorMessage(mr, "MachMessageServer::Run");
|
||||
|
||||
|
@ -45,20 +45,16 @@ started by launchd(8) as a result of a message being sent to a service declared
|
||||
in a job’s +MachServices+ dictionary (see launchd.plist(5)). The service name
|
||||
may also be completely unknown to the system.
|
||||
|
||||
*-n*, *--nonblocking*::
|
||||
Don’t wait for an exception to occur if one is not received immediately. In
|
||||
nonblocking mode, this tool exits immediately if no exception is received. The
|
||||
default mode is blocking.
|
||||
|
||||
*-p*, *--persistent*::
|
||||
Continue processing exceptions after the first one. The default mode is
|
||||
one-shot, where this tool exits after processing the first exception.
|
||||
|
||||
*-t*, *--timeout*='TIMEOUT'::
|
||||
Run for a maximum of 'TIMEOUT' seconds. This option only has an effect in
|
||||
blocking mode (when *--nonblocking* is not specified). In *--persistent* mode,
|
||||
'TIMEOUT' applies to the overall duration that this tool will run, not to the
|
||||
processing of individual exceptions.
|
||||
Run for a maximum of 'TIMEOUT' seconds. Specify +0+ to request non-blocking
|
||||
operation, in which the tool exits immediately if no exception is received. In
|
||||
*--persistent* mode, 'TIMEOUT' applies to the overall duration that this tool
|
||||
will run, not to the processing of individual exceptions. When *--timeout* is
|
||||
not specified, this tool will block indefinitely while waiting for an exception.
|
||||
|
||||
*--help*::
|
||||
Display help and exit.
|
||||
@ -92,7 +88,7 @@ bootstrap server under the name +svc+:
|
||||
$ *on_demand_service_tool --load --label=catch_exception \
|
||||
--mach-service=svc \
|
||||
$(which catch_exception_tool) --mach-service=svc \
|
||||
--file=/tmp/out --nonblocking --persistent*
|
||||
--file=/tmp/out --persistent --timeout=0*
|
||||
$ *exception_port_tool --set-handler=handler=bootstrap:svc crasher*
|
||||
Illegal instruction: 4
|
||||
$ *on_demand_service_tool --unload --label=catch_exception*
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "util/mach/exc_server_variants.h"
|
||||
#include "util/mach/exception_behaviors.h"
|
||||
#include "util/mach/mach_extensions.h"
|
||||
#include "util/mach/mach_message.h"
|
||||
#include "util/mach/mach_message_server.h"
|
||||
#include "util/mach/symbolic_constants_mach.h"
|
||||
#include "util/posix/symbolic_constants_posix.h"
|
||||
@ -43,7 +44,7 @@ struct Options {
|
||||
std::string mach_service;
|
||||
FILE* file;
|
||||
int timeout_secs;
|
||||
MachMessageServer::Nonblocking nonblocking;
|
||||
bool has_timeout;
|
||||
MachMessageServer::Persistent persistent;
|
||||
};
|
||||
|
||||
@ -171,7 +172,6 @@ void Usage(const std::string& me) {
|
||||
"\n"
|
||||
" -f, --file=FILE append information to FILE instead of stdout\n"
|
||||
" -m, --mach-service=SERVICE register SERVICE with the bootstrap server\n"
|
||||
" -n, --nonblocking don't block waiting for an exception to occur\n"
|
||||
" -p, --persistent continue processing exceptions after the first\n"
|
||||
" -t, --timeout=TIMEOUT run for a maximum of TIMEOUT seconds\n"
|
||||
" --help display this help and exit\n"
|
||||
@ -187,7 +187,6 @@ int CatchExceptionToolMain(int argc, char* argv[]) {
|
||||
// “Short” (single-character) options.
|
||||
kOptionFile = 'f',
|
||||
kOptionMachService = 'm',
|
||||
kOptionNonblocking = 'n',
|
||||
kOptionPersistent = 'p',
|
||||
kOptionTimeout = 't',
|
||||
|
||||
@ -204,7 +203,6 @@ int CatchExceptionToolMain(int argc, char* argv[]) {
|
||||
const struct option long_options[] = {
|
||||
{"file", required_argument, nullptr, kOptionFile},
|
||||
{"mach-service", required_argument, nullptr, kOptionMachService},
|
||||
{"nonblocking", no_argument, nullptr, kOptionNonblocking},
|
||||
{"persistent", no_argument, nullptr, kOptionPersistent},
|
||||
{"timeout", required_argument, nullptr, kOptionTimeout},
|
||||
{"help", no_argument, nullptr, kOptionHelp},
|
||||
@ -213,7 +211,7 @@ int CatchExceptionToolMain(int argc, char* argv[]) {
|
||||
};
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt_long(argc, argv, "f:m:npt:", long_options, nullptr)) !=
|
||||
while ((opt = getopt_long(argc, argv, "f:m:pt:", long_options, nullptr)) !=
|
||||
-1) {
|
||||
switch (opt) {
|
||||
case kOptionFile:
|
||||
@ -222,18 +220,16 @@ int CatchExceptionToolMain(int argc, char* argv[]) {
|
||||
case kOptionMachService:
|
||||
options.mach_service = optarg;
|
||||
break;
|
||||
case kOptionNonblocking:
|
||||
options.nonblocking = MachMessageServer::kNonblocking;
|
||||
break;
|
||||
case kOptionPersistent:
|
||||
options.persistent = MachMessageServer::kPersistent;
|
||||
break;
|
||||
case kOptionTimeout:
|
||||
if (!StringToNumber(optarg, &options.timeout_secs) ||
|
||||
options.timeout_secs <= 0) {
|
||||
ToolSupport::UsageHint(me, "-t requires a positive TIMEOUT");
|
||||
options.timeout_secs < 0) {
|
||||
ToolSupport::UsageHint(me, "-t requires a zero or positive TIMEOUT");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
options.has_timeout = true;
|
||||
break;
|
||||
case kOptionHelp:
|
||||
Usage(me);
|
||||
@ -285,18 +281,22 @@ int CatchExceptionToolMain(int argc, char* argv[]) {
|
||||
? MachMessageServer::kReceiveLargeIgnore
|
||||
: MachMessageServer::kReceiveLargeError;
|
||||
|
||||
mach_msg_timeout_t timeout_ms = options.timeout_secs
|
||||
? options.timeout_secs * 1000
|
||||
: MACH_MSG_TIMEOUT_NONE;
|
||||
mach_msg_timeout_t timeout_ms;
|
||||
if (!options.has_timeout) {
|
||||
timeout_ms = kMachMessageTimeoutWaitIndefinitely;
|
||||
} else if (options.timeout_secs == 0) {
|
||||
timeout_ms = kMachMessageTimeoutNonblocking;
|
||||
} else {
|
||||
timeout_ms = options.timeout_secs * 1000;
|
||||
}
|
||||
|
||||
mach_msg_return_t mr = MachMessageServer::Run(&universal_mach_exc_server,
|
||||
service_port,
|
||||
MACH_MSG_OPTION_NONE,
|
||||
options.persistent,
|
||||
options.nonblocking,
|
||||
receive_large,
|
||||
timeout_ms);
|
||||
if (mr == MACH_RCV_TIMED_OUT && options.timeout_secs && options.persistent &&
|
||||
if (mr == MACH_RCV_TIMED_OUT && options.has_timeout && options.persistent &&
|
||||
exceptions_handled) {
|
||||
// This is not an error: when exiting on timeout during persistent
|
||||
// processing and at least one exception was handled, it’s considered a
|
||||
|
@ -76,7 +76,7 @@ looking up the name +svc+:
|
||||
$ *on_demand_service_tool --load --label=catch_exception \
|
||||
--mach-service=svc \
|
||||
$(which catch_exception_tool) --mach-service=svc \
|
||||
--file=/tmp/out --nonblocking --persistent*
|
||||
--file=/tmp/out --persistent --timeout=0*
|
||||
----
|
||||
|
||||
Unregisters the on-demand server installed above:
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "util/file/fd_io.h"
|
||||
#include "util/mach/child_port.h"
|
||||
#include "util/mach/mach_extensions.h"
|
||||
#include "util/mach/mach_message.h"
|
||||
#include "util/mach/mach_message_server.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -213,9 +214,8 @@ mach_port_t ChildPortHandshake::RunServer() {
|
||||
server_port_set,
|
||||
MACH_MSG_OPTION_NONE,
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kNonblocking,
|
||||
MachMessageServer::kReceiveLargeIgnore,
|
||||
MACH_MSG_TIMEOUT_NONE);
|
||||
kMachMessageTimeoutNonblocking);
|
||||
if (mr == MACH_RCV_TIMED_OUT) {
|
||||
break;
|
||||
} else if (mr != MACH_MSG_SUCCESS) {
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "util/mach/exc_server_variants.h"
|
||||
#include "util/mach/exception_behaviors.h"
|
||||
#include "util/mach/mach_extensions.h"
|
||||
#include "util/mach/mach_message.h"
|
||||
#include "util/mach/mach_message_server.h"
|
||||
#include "util/test/mac/mach_errors.h"
|
||||
#include "util/test/mac/mach_multiprocess.h"
|
||||
|
||||
@ -141,9 +143,8 @@ class TestExcClientVariants : public MachMultiprocess,
|
||||
LocalPort(),
|
||||
MACH_MSG_OPTION_NONE,
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kBlocking,
|
||||
MachMessageServer::kReceiveLargeError,
|
||||
0);
|
||||
kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(KERN_SUCCESS, kr)
|
||||
<< MachErrorMessage(kr, "MachMessageServer::Run");
|
||||
|
||||
|
@ -1046,9 +1046,8 @@ class TestExcServerVariants : public MachMultiprocess,
|
||||
LocalPort(),
|
||||
kMachMessageOptions,
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kBlocking,
|
||||
MachMessageServer::kReceiveLargeError,
|
||||
0);
|
||||
kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(KERN_SUCCESS, kr)
|
||||
<< MachErrorMessage(kr, "MachMessageServer::Run");
|
||||
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "util/file/fd_io.h"
|
||||
#include "util/mach/exc_server_variants.h"
|
||||
#include "util/mach/mach_extensions.h"
|
||||
#include "util/mach/mach_message.h"
|
||||
#include "util/mach/mach_message_server.h"
|
||||
#include "util/misc/scoped_forbid_return.h"
|
||||
#include "util/synchronization/semaphore.h"
|
||||
#include "util/test/mac/mach_errors.h"
|
||||
@ -450,9 +452,8 @@ class TestExceptionPorts : public MachMultiprocess,
|
||||
local_port,
|
||||
MACH_MSG_OPTION_NONE,
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kBlocking,
|
||||
MachMessageServer::kReceiveLargeError,
|
||||
0);
|
||||
kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(KERN_SUCCESS, kr)
|
||||
<< MachErrorMessage(kr, "MachMessageServer::Run");
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace {
|
||||
const int kNanosecondsPerMillisecond = 1E6;
|
||||
|
||||
// TimerRunning() determines whether |deadline| has passed. If |deadline| is
|
||||
// kMachMessageWaitIndefinitely, |*timeout_options| is set to
|
||||
// kMachMessageDeadlineWaitIndefinitely, |*timeout_options| is set to
|
||||
// MACH_MSG_OPTION_NONE, |*remaining_ms| is set to MACH_MSG_TIMEOUT_NONE, and
|
||||
// this function returns true. When used with mach_msg(), this will cause
|
||||
// indefinite waiting. In any other case, |*timeout_options| is set to
|
||||
@ -34,13 +34,13 @@ const int kNanosecondsPerMillisecond = 1E6;
|
||||
// specified by |*remaining_ms|. If |deadline| is in the future, |*remaining_ms|
|
||||
// is set to the number of milliseconds remaining, which will always be a
|
||||
// positive value, and this function returns true. If |deadline| is
|
||||
// kMachMessageNonblocking (indicating that no timer is in effect),
|
||||
// kMachMessageDeadlineNonblocking (indicating that no timer is in effect),
|
||||
// |*remaining_ms| is set to zero and this function returns true. Otherwise,
|
||||
// this function sets |*remaining_ms| to zero and returns false.
|
||||
bool TimerRunning(uint64_t deadline,
|
||||
mach_msg_timeout_t* remaining_ms,
|
||||
mach_msg_option_t* timeout_options) {
|
||||
if (deadline == kMachMessageWaitIndefinitely) {
|
||||
if (deadline == kMachMessageDeadlineWaitIndefinitely) {
|
||||
*remaining_ms = MACH_MSG_TIMEOUT_NONE;
|
||||
*timeout_options = MACH_MSG_OPTION_NONE;
|
||||
return true;
|
||||
@ -48,7 +48,7 @@ bool TimerRunning(uint64_t deadline,
|
||||
|
||||
*timeout_options = MACH_SEND_TIMEOUT | MACH_RCV_TIMEOUT;
|
||||
|
||||
if (deadline == kMachMessageNonblocking) {
|
||||
if (deadline == kMachMessageDeadlineNonblocking) {
|
||||
*remaining_ms = 0;
|
||||
return true;
|
||||
}
|
||||
@ -117,12 +117,15 @@ mach_msg_return_t MachMessageWithDeadlineInternal(mach_msg_header_t* message,
|
||||
|
||||
MachMessageDeadline MachMessageDeadlineFromTimeout(
|
||||
mach_msg_timeout_t timeout_ms) {
|
||||
if (timeout_ms == 0) {
|
||||
return kMachMessageNonblocking;
|
||||
switch (timeout_ms) {
|
||||
case kMachMessageTimeoutNonblocking:
|
||||
return kMachMessageDeadlineNonblocking;
|
||||
case kMachMessageTimeoutWaitIndefinitely:
|
||||
return kMachMessageDeadlineWaitIndefinitely;
|
||||
default:
|
||||
return ClockMonotonicNanoseconds() +
|
||||
implicit_cast<uint64_t>(timeout_ms) * kNanosecondsPerMillisecond;
|
||||
}
|
||||
|
||||
return ClockMonotonicNanoseconds() +
|
||||
implicit_cast<uint64_t>(timeout_ms) * kNanosecondsPerMillisecond;
|
||||
}
|
||||
|
||||
mach_msg_return_t MachMessageWithDeadline(mach_msg_header_t* message,
|
||||
|
@ -20,12 +20,24 @@
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
//! \brief Special constants used as `mach_msg_timeout_t` values.
|
||||
enum : mach_msg_timeout_t {
|
||||
//! \brief When passed to MachMessageDeadlineFromTimeout(), that function will
|
||||
//! return #kMachMessageDeadlineNonblocking.
|
||||
kMachMessageTimeoutNonblocking = 0,
|
||||
|
||||
//! \brief When passed to MachMessageDeadlineFromTimeout(), that function will
|
||||
//! return #kMachMessageDeadlineWaitIndefinitely.
|
||||
kMachMessageTimeoutWaitIndefinitely = 0xffffffff,
|
||||
};
|
||||
|
||||
//! \brief The time before which a MachMessageWithDeadline() call should
|
||||
//! complete.
|
||||
//!
|
||||
//! A value of this type may be one of the special constants
|
||||
//! #kMachMessageNonblocking or #kMachMessageWaitIndefinitely. Any other values
|
||||
//! should be produced by calling MachMessageDeadlineFromTimeout().
|
||||
//! #kMachMessageDeadlineNonblocking or #kMachMessageDeadlineWaitIndefinitely.
|
||||
//! Any other values should be produced by calling
|
||||
//! MachMessageDeadlineFromTimeout().
|
||||
//!
|
||||
//! Internally, these are currently specified on the same time base as
|
||||
//! ClockMonotonicNanoseconds(), although this is an implementation detail.
|
||||
@ -34,11 +46,11 @@ using MachMessageDeadline = uint64_t;
|
||||
//! \brief Special constants used as \ref MachMessageDeadline values.
|
||||
enum : MachMessageDeadline {
|
||||
//! \brief MachMessageWithDeadline() should not block at all in its operation.
|
||||
kMachMessageNonblocking = 0,
|
||||
kMachMessageDeadlineNonblocking = 0,
|
||||
|
||||
//! \brief MachMessageWithDeadline() should wait indefinitely for the
|
||||
//! requested operation to complete.
|
||||
kMachMessageWaitIndefinitely = 0xffffffffffffffff,
|
||||
kMachMessageDeadlineWaitIndefinitely = 0xffffffffffffffff,
|
||||
};
|
||||
|
||||
//! \brief Computes the deadline for a specified timeout value.
|
||||
@ -47,7 +59,10 @@ enum : MachMessageDeadline {
|
||||
//! function calculates the deadline as \a timeout_ms milliseconds after it
|
||||
//! executes.
|
||||
//!
|
||||
//! If \a timeout_ms is `0`, this function will return #kMachMessageNonblocking.
|
||||
//! If \a timeout_ms is #kMachMessageDeadlineNonblocking, this function will
|
||||
//! return #kMachMessageDeadlineNonblocking. If \a timeout_ms is
|
||||
//! #kMachMessageTimeoutWaitIndefinitely, this function will return
|
||||
//! #kMachMessageDeadlineWaitIndefinitely.
|
||||
MachMessageDeadline MachMessageDeadlineFromTimeout(
|
||||
mach_msg_timeout_t timeout_ms);
|
||||
|
||||
@ -78,10 +93,10 @@ MachMessageDeadline MachMessageDeadlineFromTimeout(
|
||||
//! `MACH_RCV_TIMED_OUT`.
|
||||
//! \param[in] run_even_if_expired If `true`, a deadline that is expired when
|
||||
//! this function is called will be treated as though a deadline of
|
||||
//! #kMachMessageNonblocking had been specified. When `false`, an expired
|
||||
//! deadline will result in a `MACH_SEND_TIMED_OUT` or `MACH_RCV_TIMED_OUT`
|
||||
//! return value, even if the deadline is already expired when the function
|
||||
//! is called.
|
||||
//! #kMachMessageDeadlineNonblocking had been specified. When `false`, an
|
||||
//! expired deadline will result in a `MACH_SEND_TIMED_OUT` or
|
||||
//! `MACH_RCV_TIMED_OUT` return value, even if the deadline is already
|
||||
//! expired when the function is called.
|
||||
mach_msg_return_t MachMessageWithDeadline(mach_msg_header_t* message,
|
||||
mach_msg_option_t options,
|
||||
mach_msg_size_t receive_size,
|
||||
|
@ -116,28 +116,20 @@ mach_msg_return_t MachMessageAllocateReceive(MachMessageBuffer* request,
|
||||
// xnu-2422.110.17/libsyscall/mach/mach_msg.c mach_msg_server_once(). The server
|
||||
// callback function and |max_size| parameter have been replaced with a C++
|
||||
// interface. The |persistent| parameter has been added, allowing this method to
|
||||
// serve as a stand-in for mach_msg_server(). The |nonblocking| parameter has
|
||||
// been added, allowing blocking to be controlled directly. The |timeout_ms|
|
||||
// parameter has been added, allowing this function to not block indefinitely.
|
||||
// serve as a stand-in for mach_msg_server(). The |timeout_ms| parameter has
|
||||
// been added, allowing this function to not block indefinitely.
|
||||
//
|
||||
// static
|
||||
mach_msg_return_t MachMessageServer::Run(Interface* interface,
|
||||
mach_port_t receive_port,
|
||||
mach_msg_options_t options,
|
||||
Persistent persistent,
|
||||
Nonblocking nonblocking,
|
||||
ReceiveLarge receive_large,
|
||||
mach_msg_timeout_t timeout_ms) {
|
||||
options &= ~(MACH_RCV_MSG | MACH_SEND_MSG);
|
||||
|
||||
MachMessageDeadline deadline;
|
||||
if (nonblocking == kNonblocking) {
|
||||
deadline = kMachMessageNonblocking;
|
||||
} else if (timeout_ms == MACH_MSG_TIMEOUT_NONE) {
|
||||
deadline = kMachMessageWaitIndefinitely;
|
||||
} else {
|
||||
deadline = MachMessageDeadlineFromTimeout(timeout_ms);
|
||||
}
|
||||
const MachMessageDeadline deadline =
|
||||
MachMessageDeadlineFromTimeout(timeout_ms);
|
||||
|
||||
if (receive_large == kReceiveLargeResize) {
|
||||
options |= MACH_RCV_LARGE;
|
||||
@ -259,8 +251,9 @@ mach_msg_return_t MachMessageServer::Run(Interface* interface,
|
||||
// without considering the user-specified timeout. See 10.9.5
|
||||
// xnu-2422.115.4/osfmk/ipc/ipc_mqueue.c ipc_mqueue_send().
|
||||
const MachMessageDeadline send_deadline =
|
||||
deadline == kMachMessageWaitIndefinitely ? kMachMessageNonblocking
|
||||
: deadline;
|
||||
deadline == kMachMessageDeadlineWaitIndefinitely
|
||||
? kMachMessageDeadlineNonblocking
|
||||
: deadline;
|
||||
|
||||
kr = MachMessageWithDeadline(reply_header,
|
||||
options | MACH_SEND_MSG,
|
||||
|
@ -99,16 +99,6 @@ class MachMessageServer {
|
||||
kPersistent,
|
||||
};
|
||||
|
||||
//! \brief Informs Run() whether or not to block while waiting for requests.
|
||||
enum Nonblocking {
|
||||
//! \brief Wait for a request message if none is queued.
|
||||
kBlocking = false,
|
||||
|
||||
//! \brief Return as soon as there no request messages queued. This may
|
||||
//! result in an immediate return without handling any requests.
|
||||
kNonblocking,
|
||||
};
|
||||
|
||||
//! \brief Determines how to handle the reception of messages larger than the
|
||||
//! size of the buffer allocated to store them.
|
||||
enum ReceiveLarge {
|
||||
@ -159,28 +149,24 @@ class MachMessageServer {
|
||||
//! `MACH_MSG_OPTION_NONE`. `MACH_RCV_LARGE` when specified here is
|
||||
//! ignored. Set \a receive_large to #kReceiveLargeResize instead.
|
||||
//! \param[in] persistent Chooses between one-shot and persistent operation.
|
||||
//! \param[in] nonblocking Chooses between blocking and nonblocking operation.
|
||||
//! \param[in] receive_large Determines the behavior upon encountering a
|
||||
//! message larger than the receive buffer’s size.
|
||||
//! \param[in] timeout_ms When \a nonblocking is `false`, the the maximum
|
||||
//! duration that this entire function will run, in milliseconds, or
|
||||
//! `MACH_MSG_TIMEOUT_NONE` to specify no timeout (infinite waiting). When
|
||||
//! \a nonblocking is `true`, this parameter has no effect. When \a
|
||||
//! persistent is `true`, the timeout applies to the overall duration of
|
||||
//! this function, not to any individual `mach_msg()` call.
|
||||
//! \param[in] timeout_ms The maximum duration that this entire function will
|
||||
//! run, in milliseconds. This may be #kMachMessageTimeoutNonblocking or
|
||||
//! #kMachMessageTimeoutWaitIndefinitely. When \a persistent is `true`,
|
||||
//! the timeout applies to the overall duration of this function, not to
|
||||
//! any individual `mach_msg()` call.
|
||||
//!
|
||||
//! \return On success, `KERN_SUCCESS` (when \a persistent is `false`) or
|
||||
//! `MACH_RCV_TIMED_OUT` (when \a persistent and \a nonblocking are both
|
||||
//! `true`, or when \a persistent is `true`, \a nonblocking is `false`,
|
||||
//! and \a timeout is not `MACH_MSG_TIMEOUT_NONE`. This function has no
|
||||
//! successful return value when \a persistent is `true`, \a nonblocking
|
||||
//! is `false`, and \a timeout is `MACH_MSG_TIMEOUT_NONE`. On failure,
|
||||
//! returns a value identifying the nature of the error.
|
||||
//! `MACH_RCV_TIMED_OUT` (when \a persistent is `true` and \a timeout_ms
|
||||
//! is not #kMachMessageTimeoutWaitIndefinitely). This function has no
|
||||
//! successful return value when \a persistent is `true` and \a timeout_ms
|
||||
//! is #kMachMessageTimeoutWaitIndefinitely. On failure, returns a value
|
||||
//! identifying the nature of the error.
|
||||
static mach_msg_return_t Run(Interface* interface,
|
||||
mach_port_t receive_port,
|
||||
mach_msg_options_t options,
|
||||
Persistent persistent,
|
||||
Nonblocking nonblocking,
|
||||
ReceiveLarge receive_large,
|
||||
mach_msg_timeout_t timeout_ms);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "util/file/fd_io.h"
|
||||
#include "util/mach/mach_extensions.h"
|
||||
#include "util/mach/mach_message.h"
|
||||
#include "util/test/mac/mach_errors.h"
|
||||
#include "util/test/mac/mach_multiprocess.h"
|
||||
|
||||
@ -59,9 +60,8 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
parent_wait_for_child_pipe(false),
|
||||
server_options(MACH_MSG_OPTION_NONE),
|
||||
server_persistent(MachMessageServer::kOneShot),
|
||||
server_nonblocking(MachMessageServer::kBlocking),
|
||||
server_receive_large(MachMessageServer::kReceiveLargeError),
|
||||
server_timeout_ms(MACH_MSG_TIMEOUT_NONE),
|
||||
server_timeout_ms(kMachMessageTimeoutWaitIndefinitely),
|
||||
server_mig_retcode(KERN_SUCCESS),
|
||||
server_destroy_complex(true),
|
||||
expect_server_destroyed_complex(true),
|
||||
@ -93,13 +93,11 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
// Whether the server should run in one-shot or persistent mode.
|
||||
MachMessageServer::Persistent server_persistent;
|
||||
|
||||
// Whether the server should run in blocking or nonblocking mode.
|
||||
MachMessageServer::Nonblocking server_nonblocking;
|
||||
|
||||
// The strategy for handling large messages.
|
||||
MachMessageServer::ReceiveLarge server_receive_large;
|
||||
|
||||
// The server’s timeout.
|
||||
// The server’s timeout in milliseconds, or kMachMessageTimeoutNonblocking
|
||||
// or kMachMessageTimeoutWaitIndefinitely.
|
||||
mach_msg_timeout_t server_timeout_ms;
|
||||
|
||||
// The return code that the server returns to the client via the
|
||||
@ -352,7 +350,6 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
local_port,
|
||||
options_.server_options,
|
||||
options_.server_persistent,
|
||||
options_.server_nonblocking,
|
||||
options_.server_receive_large,
|
||||
options_.server_timeout_ms)))
|
||||
<< MachErrorMessage(kr, "MachMessageServer");
|
||||
@ -616,7 +613,7 @@ TEST(MachMessageServer, NonblockingNoMessage) {
|
||||
// server should return immediately without processing any message.
|
||||
TestMachMessageServer::Options options;
|
||||
options.expect_server_interface_method_called = false;
|
||||
options.server_nonblocking = MachMessageServer::kNonblocking;
|
||||
options.server_timeout_ms = kMachMessageTimeoutNonblocking;
|
||||
options.expect_server_result = MACH_RCV_TIMED_OUT;
|
||||
options.expect_server_transaction_count = 0;
|
||||
options.client_send_request_count = 0;
|
||||
@ -644,7 +641,7 @@ TEST(MachMessageServer, Nonblocking) {
|
||||
// nonblocking mode.
|
||||
TestMachMessageServer::Options options;
|
||||
options.parent_wait_for_child_pipe = true;
|
||||
options.server_nonblocking = MachMessageServer::kNonblocking;
|
||||
options.server_timeout_ms = kMachMessageTimeoutNonblocking;
|
||||
TestMachMessageServer test_mach_message_server(options);
|
||||
test_mach_message_server.Test();
|
||||
}
|
||||
@ -698,7 +695,7 @@ TEST(MachMessageServer, PersistentNonblockingFourMessages) {
|
||||
TestMachMessageServer::Options options;
|
||||
options.parent_wait_for_child_pipe = true;
|
||||
options.server_persistent = MachMessageServer::kPersistent;
|
||||
options.server_nonblocking = MachMessageServer::kNonblocking;
|
||||
options.server_timeout_ms = kMachMessageTimeoutNonblocking;
|
||||
options.expect_server_result = MACH_RCV_TIMED_OUT;
|
||||
options.expect_server_transaction_count = kTransactionCount;
|
||||
options.child_wait_for_parent_pipe_early = true;
|
||||
|
@ -23,16 +23,21 @@ namespace test {
|
||||
namespace {
|
||||
|
||||
TEST(MachMessage, MachMessageDeadlineFromTimeout) {
|
||||
MachMessageDeadline deadline_0 = MachMessageDeadlineFromTimeout(0);
|
||||
EXPECT_EQ(kMachMessageNonblocking, deadline_0);
|
||||
MachMessageDeadline deadline_0 =
|
||||
MachMessageDeadlineFromTimeout(kMachMessageTimeoutNonblocking);
|
||||
EXPECT_EQ(kMachMessageDeadlineNonblocking, deadline_0);
|
||||
|
||||
deadline_0 =
|
||||
MachMessageDeadlineFromTimeout(kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(kMachMessageDeadlineWaitIndefinitely, deadline_0);
|
||||
|
||||
deadline_0 = MachMessageDeadlineFromTimeout(1);
|
||||
MachMessageDeadline deadline_1 = MachMessageDeadlineFromTimeout(100);
|
||||
|
||||
EXPECT_NE(kMachMessageNonblocking, deadline_0);
|
||||
EXPECT_NE(kMachMessageWaitIndefinitely, deadline_0);
|
||||
EXPECT_NE(kMachMessageNonblocking, deadline_1);
|
||||
EXPECT_NE(kMachMessageWaitIndefinitely, deadline_1);
|
||||
EXPECT_NE(kMachMessageDeadlineNonblocking, deadline_0);
|
||||
EXPECT_NE(kMachMessageDeadlineWaitIndefinitely, deadline_0);
|
||||
EXPECT_NE(kMachMessageDeadlineNonblocking, deadline_1);
|
||||
EXPECT_NE(kMachMessageDeadlineWaitIndefinitely, deadline_1);
|
||||
EXPECT_GE(deadline_1, deadline_0);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user