Make JackMachSemaphore more robust, dont use thread_terminate

Fixes #841
This commit is contained in:
falkTX 2022-04-15 20:02:58 +01:00
parent 5aa5861af0
commit 45042beac5
4 changed files with 58 additions and 18 deletions

View File

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

View File

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

View File

@ -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;
}

View File

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