@@ -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() | ||||