| @@ -305,7 +305,7 @@ bool JackMachSemaphore::ConnectInput(const char* client_name, const char* server | |||||
| } else { | } else { | ||||
| fSemaphore = msg.hdr.msgh_remote_port; | fSemaphore = msg.hdr.msgh_remote_port; | ||||
| jack_log("JackMachSemaphore::Connect: OK, name = %s ", fName); | |||||
| jack_log("JackMachSemaphore::Connect: OK, name = %s", fName); | |||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| @@ -353,17 +353,22 @@ bool JackMachSemaphore::Disconnect() | |||||
| // Server side : destroy the JackGlobals | // Server side : destroy the JackGlobals | ||||
| void JackMachSemaphore::Destroy() | void JackMachSemaphore::Destroy() | ||||
| { | { | ||||
| const mach_port_t task = mach_task_self(); | |||||
| kern_return_t res; | kern_return_t res; | ||||
| mach_port_t task = mach_task_self(); | |||||
| if (fSemaphore == MACH_PORT_NULL) { | if (fSemaphore == MACH_PORT_NULL) { | ||||
| jack_error("JackMachSemaphore::Destroy semaphore is MACH_PORT_NULL; already destroyed?"); | jack_error("JackMachSemaphore::Destroy semaphore is MACH_PORT_NULL; already destroyed?"); | ||||
| return; | return; | ||||
| } | } | ||||
| if (fSemServer && fSemServer->Invalidate()) { | |||||
| fServicePort = MACH_PORT_NULL; | |||||
| fSemaphore = MACH_PORT_NULL; | |||||
| } | |||||
| if (fThreadSemServer) { | 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. | // Oh dear. How sad. Never mind. | ||||
| } | } | ||||
| @@ -378,16 +383,20 @@ void JackMachSemaphore::Destroy() | |||||
| delete server; | 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); | jack_log("JackMachSemaphore::Destroy: OK, name = %s", fName); | ||||
| @@ -34,21 +34,25 @@ class SERVER_EXPORT JackMachSemaphoreServer : public JackRunnableInterface | |||||
| { | { | ||||
| private: | private: | ||||
| /*! \brief The semaphore send right that will be dispatched to clients. */ | /*! \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. */ | /*! \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 | /*! \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. */ | * 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: | 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 Execute() override; | ||||
| bool Invalidate(); | |||||
| }; | }; | ||||
| } // end of namespace | } // end of namespace | ||||
| @@ -52,9 +52,14 @@ bool JackMachSemaphoreServer::Execute() { | |||||
| MACH_PORT_NULL | 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) { | if (recv_err != MACH_MSG_SUCCESS) { | ||||
| jack_mach_error(recv_err, "receive error"); | 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. | /* 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"); | 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; | return true; | ||||
| } | } | ||||
| @@ -160,6 +160,8 @@ int JackMachThread::GetParams(jack_native_thread_t thread, UInt64* period, UInt6 | |||||
| int JackMachThread::Kill() | 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 | if (fThread != (jack_native_thread_t)NULL) { // If thread has been started | ||||
| jack_log("JackMachThread::Kill"); | jack_log("JackMachThread::Kill"); | ||||
| mach_port_t machThread = pthread_mach_thread_np(fThread); | mach_port_t machThread = pthread_mach_thread_np(fThread); | ||||
| @@ -170,6 +172,9 @@ int JackMachThread::Kill() | |||||
| } else { | } else { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| #else | |||||
| return JackPosixThread::Kill(); | |||||
| #endif | |||||
| } | } | ||||
| int JackMachThread::AcquireRealTime() | int JackMachThread::AcquireRealTime() | ||||