+static inline boolean_t
+mach_msg_server_is_recoverable_send_error(kern_return_t kr)
+{
+ switch (kr) {
+ case MACH_SEND_INVALID_DEST:
+ case MACH_SEND_TIMED_OUT:
+ case MACH_SEND_INTERRUPTED:
+ return TRUE;
+ default:
+ /*
+ * Other errors mean that the message may have been partially destroyed
+ * by the kernel, and these can't be recovered and may leak resources.
+ */
+ return FALSE;
+ }
+}
+
+static kern_return_t
+mach_msg_server_mig_return_code(mig_reply_error_t *reply)
+{
+ /*
+ * If the message is complex, it is assumed that the reply was successful,
+ * as the RetCode is where the count of out of line descriptors is.
+ *
+ * If not, we read RetCode.
+ */
+ if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
+ return KERN_SUCCESS;
+ }
+ return reply->RetCode;
+}
+
+static void
+mach_msg_server_consume_unsent_message(mach_msg_header_t *hdr)
+{
+ /* mach_msg_destroy doesn't handle the local port */
+ mach_port_t port = hdr->msgh_local_port;
+ if (MACH_PORT_VALID(port)) {
+ switch (MACH_MSGH_BITS_LOCAL(hdr->msgh_bits)) {
+ case MACH_MSG_TYPE_MOVE_SEND:
+ case MACH_MSG_TYPE_MOVE_SEND_ONCE:
+ /* destroy the send/send-once right */
+ (void) mach_port_deallocate(mach_task_self_, port);
+ hdr->msgh_local_port = MACH_PORT_NULL;
+ break;
+ }
+ }
+ mach_msg_destroy(hdr);
+}
+