| 
							- /*
 - Copyright (C) 2021 Peter Bridgman
 - 
 - This program is free software; you can redistribute it and/or modify
 - it under the terms of the GNU Lesser General Public License as published by
 - the Free Software Foundation; either version 2.1 of the License, or
 - (at your option) any later version.
 - 
 - This program is distributed in the hope that it will be useful,
 - but WITHOUT ANY WARRANTY; without even the implied warranty of
 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - GNU Lesser General Public License for more details.
 - 
 - You should have received a copy of the GNU Lesser General Public License
 - along with this program; if not, write to the Free Software
 - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 - 
 - */
 - 
 - #include "JackMachSemaphoreServer.h"
 - #include "JackMachUtils.h"
 - #include "JackConstants.h"
 - #include "JackTools.h"
 - #include "JackError.h"
 - 
 - #include <mach/message.h>
 - 
 - #define jack_mach_error(kern_result, message) \
 -         jack_mach_error_uncurried("JackMachSemaphoreServer", kern_result, message)
 - 
 - namespace Jack
 - {
 - 
 - bool JackMachSemaphoreServer::Execute() {
 -     jack_log("JackMachSemaphoreServer::Execute: %s", fName);
 - 
 -     /* Setup a message struct in our local stack frame which we can receive messages into and send
 -      * messages from. */
 -     struct {
 -         mach_msg_header_t hdr;
 -         mach_msg_trailer_t trailer;
 -     } msg;
 - 
 -     // Block until we receive a message on the fServerReceive port.
 -     mach_msg_return_t recv_err = mach_msg(
 -         &msg.hdr,
 -         MACH_RCV_MSG,
 -         0,
 -         sizeof(msg),
 -         fServerReceive,
 -         MACH_MSG_TIMEOUT_NONE,
 -         MACH_PORT_NULL
 -     );
 - 
 -     // this error is expected when deleting ports, we get notified that they somehow changed
 -     if (recv_err == MACH_RCV_PORT_CHANGED) {
 -         return fRunning;
 -     }
 - 
 -     if (recv_err != MACH_MSG_SUCCESS) {
 -         jack_mach_error(recv_err, "receive error");
 -         return fRunning; // Continue processing more connections
 -     }
 - 
 -     /* We're going to reuse the message struct that we received the message into to send a reply.
 -      * Setup the semaphore send port that we want to give to the client as the local port... */
 -     msg.hdr.msgh_local_port = fSemaphore;
 - 
 -     /*
 -      * ... to be returned by copy (_COPY_SEND), to a destination that is _SEND_ONCE that we no
 -      * longer require. That destination will have been set by the client as their local_port, so
 -      * will now already be the remote_port in the message we received (nifty, eh?).
 -      */
 -     msg.hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, MACH_MSG_TYPE_COPY_SEND);
 - 
 -     mach_msg_return_t send_err = mach_msg(
 -         &msg.hdr,
 -         MACH_SEND_MSG,
 -         sizeof(msg.hdr), // no trailer on send
 -         0,
 -         MACH_PORT_NULL,
 -         MACH_MSG_TIMEOUT_NONE,
 -         MACH_PORT_NULL);
 - 
 -     if (send_err != MACH_MSG_SUCCESS) {
 -         jack_mach_error(send_err, "send error");
 -     }
 - 
 -     return fRunning;
 - }
 - 
 - bool JackMachSemaphoreServer::Invalidate() {
 -     fRunning = false;
 - 
 -     const mach_port_t task = mach_task_self();
 -     kern_return_t res;
 - 
 -     if ((res = mach_port_destroy(task, fServerReceive)) != KERN_SUCCESS) {
 -         jack_mach_error(res, "failed to destroy IPC port");
 -     }
 - 
 -     if ((res = semaphore_destroy(task, fSemaphore)) != KERN_SUCCESS) {
 -         jack_mach_error(res, "failed to destroy semaphore");
 -     }
 - 
 -     return true;
 - }
 - 
 - } // end of namespace
 
 
  |