ipc: Make send_and_get_reply thread safe

When multiple threads call OpenXR functions, make sure one thread
can not read the reply meant for another thread.

Unfortunately this also blocks other OpenXR functions from being
called while xrWaitFrame() is blocking.
This commit is contained in:
Christoph Haag 2020-05-01 16:11:26 +02:00
parent d491f59b55
commit 7ab1ca727f
3 changed files with 24 additions and 1 deletions

View file

@ -13,6 +13,8 @@
#include "xrt/xrt_compiler.h"
#include "ipc_protocol.h"
#include "util/u_threading.h"
#include <stdio.h>
@ -77,6 +79,8 @@ typedef struct ipc_connection
struct ipc_shared_memory *ism;
int ism_fd;
struct os_mutex mutex;
bool print_debug; // TODO: link to settings
bool print_spew; // TODO: link to settings

View file

@ -149,6 +149,8 @@ ipc_client_instance_destroy(struct xrt_instance *xinst)
if (ii->ipc_c.socket_fd >= 0)
close(ii->ipc_c.socket_fd);
os_mutex_destroy(&ii->ipc_c.mutex);
free(ii);
}
@ -230,6 +232,8 @@ ipc_instance_create(struct xrt_instance **out_xinst)
*out_xinst = &ii->base;
os_mutex_init(&ii->ipc_c.mutex);
return 0;
}

View file

@ -17,7 +17,6 @@
#include <string.h>
#include <sys/socket.h>
ipc_result_t
ipc_client_send_and_get_reply(struct ipc_connection *ipc_c,
void *msg_ptr,
@ -25,14 +24,19 @@ ipc_client_send_and_get_reply(struct ipc_connection *ipc_c,
void *reply_ptr,
size_t reply_size)
{
// Other threads must not read/write the fd while we wait for reply
os_mutex_lock(&ipc_c->mutex);
if (ipc_c->socket_fd < 0) {
IPC_ERROR(ipc_c, "Error sending - not connected!");
os_mutex_unlock(&ipc_c->mutex);
return IPC_FAILURE;
}
ssize_t len = send(ipc_c->socket_fd, msg_ptr, msg_size, 0);
if ((size_t)len != msg_size) {
IPC_ERROR(ipc_c, "Error sending - cannot continue!");
os_mutex_unlock(&ipc_c->mutex);
return IPC_FAILURE;
}
@ -51,17 +55,21 @@ ipc_client_send_and_get_reply(struct ipc_connection *ipc_c,
msg.msg_flags = 0;
len = recvmsg(ipc_c->socket_fd, &msg, 0);
if (len < 0) {
IPC_ERROR(ipc_c, "recvmsg failed with error: %s",
strerror(errno));
os_mutex_unlock(&ipc_c->mutex);
return IPC_FAILURE;
}
if ((size_t)len != reply_size) {
IPC_ERROR(ipc_c, "recvmsg failed with error: wrong size");
os_mutex_unlock(&ipc_c->mutex);
return IPC_FAILURE;
}
os_mutex_unlock(&ipc_c->mutex);
return IPC_SUCCESS;
}
@ -74,8 +82,11 @@ ipc_client_send_and_get_reply_fds(ipc_connection_t *ipc_c,
int *fds,
size_t num_fds)
{
os_mutex_lock(&ipc_c->mutex);
if (send(ipc_c->socket_fd, msg_ptr, msg_size, 0) == -1) {
IPC_ERROR(ipc_c, "Error sending - cannot continue!");
os_mutex_unlock(&ipc_c->mutex);
return IPC_FAILURE;
}
@ -98,17 +109,21 @@ ipc_client_send_and_get_reply_fds(ipc_connection_t *ipc_c,
if (len < 0) {
IPC_ERROR(ipc_c, "recvmsg failed with error: %s",
strerror(errno));
os_mutex_unlock(&ipc_c->mutex);
return -1;
}
if (len == 0) {
IPC_ERROR(ipc_c, "recvmsg failed with error: no data");
os_mutex_unlock(&ipc_c->mutex);
return -1;
}
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
memcpy(fds, (int *)CMSG_DATA(cmsg), fds_size);
os_mutex_unlock(&ipc_c->mutex);
return IPC_SUCCESS;
}