| @@ -305,7 +305,7 @@ bool JackMachSemaphore::ConnectInput(const char* client_name, const char* server | |||
| } else { | |||
| fSemaphore = msg.hdr.msgh_remote_port; | |||
| jack_log("JackMachSemaphore::Connect: OK, name = %s ", fName); | |||
| jack_log("JackMachSemaphore::Connect: OK, name = %s", fName); | |||
| return true; | |||
| } | |||
| } | |||
| @@ -353,17 +353,22 @@ bool JackMachSemaphore::Disconnect() | |||
| // Server side : destroy the JackGlobals | |||
| void JackMachSemaphore::Destroy() | |||
| { | |||
| const mach_port_t task = mach_task_self(); | |||
| kern_return_t res; | |||
| mach_port_t task = mach_task_self(); | |||
| if (fSemaphore == MACH_PORT_NULL) { | |||
| jack_error("JackMachSemaphore::Destroy semaphore is MACH_PORT_NULL; already destroyed?"); | |||
| return; | |||
| } | |||
| if (fSemServer && fSemServer->Invalidate()) { | |||
| fServicePort = MACH_PORT_NULL; | |||
| fSemaphore = MACH_PORT_NULL; | |||
| } | |||
| if (fThreadSemServer) { | |||
| if (fThreadSemServer->Kill() < 0) { | |||
| jack_error("JackMachSemaphore::Destroy failed to kill semaphore server thread..."); | |||
| if (fThreadSemServer->Stop() < 0) { | |||
| jack_error("JackMachSemaphore::Destroy failed to stop semaphore server thread..."); | |||
| // Oh dear. How sad. Never mind. | |||
| } | |||
| @@ -378,16 +383,20 @@ void JackMachSemaphore::Destroy() | |||
| delete server; | |||
| } | |||
| if ((res = mach_port_destroy(task, fServicePort)) != KERN_SUCCESS) { | |||
| jack_mach_error(res, "failed to destroy IPC port"); | |||
| } else { | |||
| fServicePort = MACH_PORT_NULL; | |||
| if (fServicePort != MACH_PORT_NULL) { | |||
| if ((res = mach_port_destroy(task, fServicePort)) != KERN_SUCCESS) { | |||
| jack_mach_error(res, "failed to destroy IPC port"); | |||
| } else { | |||
| fServicePort = MACH_PORT_NULL; | |||
| } | |||
| } | |||
| if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) { | |||
| jack_mach_error(res, "failed to destroy semaphore"); | |||
| } else { | |||
| fSemaphore = MACH_PORT_NULL; | |||
| if (fSemaphore != MACH_PORT_NULL) { | |||
| if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) { | |||
| jack_mach_error(res, "failed to destroy semaphore"); | |||
| } else { | |||
| fSemaphore = MACH_PORT_NULL; | |||
| } | |||
| } | |||
| jack_log("JackMachSemaphore::Destroy: OK, name = %s", fName); | |||
| @@ -34,21 +34,25 @@ class SERVER_EXPORT JackMachSemaphoreServer : public JackRunnableInterface | |||
| { | |||
| private: | |||
| /*! \brief The semaphore send right that will be dispatched to clients. */ | |||
| semaphore_t fSemaphore; | |||
| const semaphore_t fSemaphore; | |||
| /*! \brief The port on which we will listen for IPC messages. */ | |||
| mach_port_t fServerReceive; | |||
| const mach_port_t fServerReceive; | |||
| /*! \brief A pointer to a null-terminated string buffer that will be read to obtain the | |||
| * server name for reporting purposes. Not managed at all by this type. */ | |||
| char* fName; | |||
| const char* const fName; | |||
| /*! \brief Whether thread should keep running. */ | |||
| bool fRunning; | |||
| public: | |||
| JackMachSemaphoreServer(semaphore_t semaphore, mach_port_t server_recv, char* name): | |||
| fSemaphore(semaphore), fServerReceive(server_recv), fName(name) | |||
| JackMachSemaphoreServer(semaphore_t semaphore, mach_port_t server_recv, const char* name): | |||
| fSemaphore(semaphore), fServerReceive(server_recv), fName(name), fRunning(true) | |||
| {} | |||
| bool Execute() override; | |||
| bool Invalidate(); | |||
| }; | |||
| } // end of namespace | |||
| @@ -52,9 +52,14 @@ bool JackMachSemaphoreServer::Execute() { | |||
| 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 true; // Continue processing more connections | |||
| return fRunning; // Continue processing more connections | |||
| } | |||
| /* We're going to reuse the message struct that we received the message into to send a reply. | |||
| @@ -81,6 +86,23 @@ bool JackMachSemaphoreServer::Execute() { | |||
| 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; | |||
| } | |||
| @@ -160,6 +160,8 @@ int JackMachThread::GetParams(jack_native_thread_t thread, UInt64* period, UInt6 | |||
| int JackMachThread::Kill() | |||
| { | |||
| #if 0 | |||
| // NOTE: starting macOS 12, this code no longer works | |||
| if (fThread != (jack_native_thread_t)NULL) { // If thread has been started | |||
| jack_log("JackMachThread::Kill"); | |||
| mach_port_t machThread = pthread_mach_thread_np(fThread); | |||
| @@ -170,6 +172,9 @@ int JackMachThread::Kill() | |||
| } else { | |||
| return -1; | |||
| } | |||
| #else | |||
| return JackPosixThread::Kill(); | |||
| #endif | |||
| } | |||
| int JackMachThread::AcquireRealTime() | |||