| @@ -128,6 +128,11 @@ bool JackMachSemaphore::TimedWait(long usec) | |||||
| */ | */ | ||||
| bool JackMachSemaphore::Allocate(const char* client_name, const char* server_name, int value) | bool JackMachSemaphore::Allocate(const char* client_name, const char* server_name, int value) | ||||
| { | { | ||||
| if (fSemaphore != MACH_PORT_NULL) { | |||||
| jack_error("JackMachSemaphore::Allocate: Semaphore already allocated; called twice? [%s]", fName); | |||||
| return false; | |||||
| } | |||||
| BuildName(client_name, server_name, fName, sizeof(fName)); | BuildName(client_name, server_name, fName, sizeof(fName)); | ||||
| mach_port_t task = mach_task_self(); | mach_port_t task = mach_task_self(); | ||||
| @@ -147,16 +152,28 @@ bool JackMachSemaphore::Allocate(const char* client_name, const char* server_nam | |||||
| if ((res = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &fServicePort)) != KERN_SUCCESS) { | if ((res = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &fServicePort)) != KERN_SUCCESS) { | ||||
| jack_mach_error(res, "failed to allocate IPC port"); | jack_mach_error(res, "failed to allocate IPC port"); | ||||
| // Cleanup created semaphore | |||||
| this->Destroy(); | |||||
| return false; | return false; | ||||
| } | } | ||||
| if ((res = mach_port_insert_right(mach_task_self(), fServicePort, fServicePort, MACH_MSG_TYPE_MAKE_SEND)) != KERN_SUCCESS) { | if ((res = mach_port_insert_right(mach_task_self(), fServicePort, fServicePort, MACH_MSG_TYPE_MAKE_SEND)) != KERN_SUCCESS) { | ||||
| jack_mach_error(res, "failed to obtain send right for IPC port"); | jack_mach_error(res, "failed to obtain send right for IPC port"); | ||||
| // Cleanup created semaphore & mach port | |||||
| this->Destroy(); | |||||
| return false; | return false; | ||||
| } | } | ||||
| if ((res = bootstrap_register(fBootPort, fName, fServicePort)) != KERN_SUCCESS) { | if ((res = bootstrap_register(fBootPort, fName, fServicePort)) != KERN_SUCCESS) { | ||||
| jack_mach_bootstrap_err(res, "can't register IPC port with bootstrap server", fName); | jack_mach_bootstrap_err(res, "can't register IPC port with bootstrap server", fName); | ||||
| // Cleanup created semaphore & mach port | |||||
| this->Destroy(); | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -165,6 +182,10 @@ bool JackMachSemaphore::Allocate(const char* client_name, const char* server_nam | |||||
| if (fThreadSemServer->Start() < 0) { | if (fThreadSemServer->Start() < 0) { | ||||
| jack_error("JackMachSemaphore::Allocate: failed to start semaphore IPC server thread [%s]", fName); | jack_error("JackMachSemaphore::Allocate: failed to start semaphore IPC server thread [%s]", fName); | ||||
| // Cleanup created semaphore, mach port (incl. service registration), and server | |||||
| this->Destroy(); | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -201,7 +222,7 @@ bool JackMachSemaphore::ConnectInput(const char* client_name, const char* server | |||||
| } | } | ||||
| if ((res = bootstrap_look_up(fBootPort, fName, &fServicePort)) != KERN_SUCCESS) { | if ((res = bootstrap_look_up(fBootPort, fName, &fServicePort)) != KERN_SUCCESS) { | ||||
| jack_mach_bootstrap_err(res, "can't find mach semaphore", fName); | |||||
| jack_mach_bootstrap_err(res, "can't find IPC service port to request semaphore", fName); | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -209,6 +230,13 @@ bool JackMachSemaphore::ConnectInput(const char* client_name, const char* server | |||||
| if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &semaphore_req_port)) != KERN_SUCCESS) { | if ((res = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &semaphore_req_port)) != KERN_SUCCESS) { | ||||
| jack_mach_error(res, "failed to allocate request port"); | jack_mach_error(res, "failed to allocate request port"); | ||||
| if ((res = mach_port_deallocate(task, fServicePort)) != KERN_SUCCESS) { | |||||
| jack_mach_error(res, "failed to deallocate IPC service port during cleanup"); | |||||
| } else { | |||||
| fServicePort = MACH_PORT_NULL; | |||||
| } | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -226,7 +254,6 @@ bool JackMachSemaphore::ConnectInput(const char* client_name, const char* server | |||||
| msg.hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); | msg.hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); | ||||
| msg.hdr.msgh_local_port = semaphore_req_port; | msg.hdr.msgh_local_port = semaphore_req_port; | ||||
| msg.hdr.msgh_remote_port = fServicePort; | msg.hdr.msgh_remote_port = fServicePort; | ||||
| fServicePort = MACH_PORT_NULL; // We moved it into the message and away to the destination | |||||
| mach_msg_return_t send_err = mach_msg( | mach_msg_return_t send_err = mach_msg( | ||||
| &msg.hdr, | &msg.hdr, | ||||
| @@ -239,7 +266,20 @@ bool JackMachSemaphore::ConnectInput(const char* client_name, const char* server | |||||
| if (send_err != MACH_MSG_SUCCESS) { | if (send_err != MACH_MSG_SUCCESS) { | ||||
| jack_mach_error(send_err, "failed to send semaphore port request IPC"); | jack_mach_error(send_err, "failed to send semaphore port request IPC"); | ||||
| if ((res = mach_port_deallocate(task, fServicePort)) != KERN_SUCCESS) { | |||||
| jack_mach_error(res, "failed to deallocate IPC service port during cleanup"); | |||||
| } else { | |||||
| fServicePort = MACH_PORT_NULL; | |||||
| } | |||||
| if ((res = mach_port_destroy(task, semaphore_req_port)) != KERN_SUCCESS) { | |||||
| jack_mach_error(res, "failed to destroy IPC request port during cleanup"); | |||||
| } | |||||
| return false; | return false; | ||||
| } else { | |||||
| fServicePort = MACH_PORT_NULL; // We moved it into the message and away to the destination | |||||
| } | } | ||||
| mach_msg_return_t recv_err = mach_msg( | mach_msg_return_t recv_err = mach_msg( | ||||
| @@ -252,21 +292,22 @@ bool JackMachSemaphore::ConnectInput(const char* client_name, const char* server | |||||
| MACH_PORT_NULL | MACH_PORT_NULL | ||||
| ); | ); | ||||
| if (recv_err != MACH_MSG_SUCCESS) { | |||||
| jack_mach_error(recv_err, "failed to receive semaphore port"); | |||||
| return false; | |||||
| } | |||||
| fSemaphore = msg.hdr.msgh_remote_port; | |||||
| // Don't leak ports: destroy the port we created to send/receive the request | |||||
| /* Don't leak ports: irrespective of if we succeeded to read or not, destroy the port we created | |||||
| * to send/receive the request as we have no further use for it either way. */ | |||||
| if ((res = mach_port_destroy(task, semaphore_req_port)) != KERN_SUCCESS) { | if ((res = mach_port_destroy(task, semaphore_req_port)) != KERN_SUCCESS) { | ||||
| jack_mach_error(res, "failed to destroy semaphore_req_port"); | jack_mach_error(res, "failed to destroy semaphore_req_port"); | ||||
| // This isn't good, but doesn't actually stop the semaphore from working... don't bail | // This isn't good, but doesn't actually stop the semaphore from working... don't bail | ||||
| } | } | ||||
| jack_log("JackMachSemaphore::Connect: OK, name = %s ", fName); | |||||
| return true; | |||||
| if (recv_err != MACH_MSG_SUCCESS) { | |||||
| jack_mach_error(recv_err, "failed to receive semaphore port"); | |||||
| return false; | |||||
| } else { | |||||
| fSemaphore = msg.hdr.msgh_remote_port; | |||||
| jack_log("JackMachSemaphore::Connect: OK, name = %s ", fName); | |||||
| return true; | |||||
| } | |||||
| } | } | ||||
| bool JackMachSemaphore::Connect(const char* name, const char* server_name) | bool JackMachSemaphore::Connect(const char* name, const char* server_name) | ||||
| @@ -295,6 +336,8 @@ bool JackMachSemaphore::Disconnect() | |||||
| if ((res = mach_port_deallocate(task, fServicePort)) != KERN_SUCCESS) { | if ((res = mach_port_deallocate(task, fServicePort)) != KERN_SUCCESS) { | ||||
| jack_mach_error(res, "failed to deallocate stray service port"); | jack_mach_error(res, "failed to deallocate stray service port"); | ||||
| // Continue cleanup even if this fails; don't bail | // Continue cleanup even if this fails; don't bail | ||||
| } else { | |||||
| fServicePort = MACH_PORT_NULL; | |||||
| } | } | ||||
| } | } | ||||