libobs/callback: Make proc_handler_t threadsafe

Add mutexes to protect against multi-threaded memory access
violations.
This commit is contained in:
tt2468 2021-09-02 08:23:56 -07:00 committed by Jim
parent c46a719c9c
commit 23cda97a54

View file

@ -15,6 +15,7 @@
*/
#include "../util/darray.h"
#include "../util/threading.h"
#include "decl.h"
#include "proc.h"
@ -32,24 +33,50 @@ static inline void proc_info_free(struct proc_info *pi)
struct proc_handler {
/* TODO: replace with hash table lookup? */
pthread_mutex_t mutex;
DARRAY(struct proc_info) procs;
};
static struct proc_info *getproc(proc_handler_t *handler, const char *name)
{
for (size_t i = 0; i < handler->procs.num; i++) {
struct proc_info *info = handler->procs.array + i;
if (strcmp(info->func.name, name) == 0) {
return info;
}
}
return NULL;
}
/* ------------------------------------------------------------------------- */
proc_handler_t *proc_handler_create(void)
{
struct proc_handler *handler = bmalloc(sizeof(struct proc_handler));
if (pthread_mutex_init_recursive(&handler->mutex) != 0) {
blog(LOG_ERROR, "Couldn't create proc_handler mutex");
bfree(handler);
return NULL;
}
da_init(handler->procs);
return handler;
}
void proc_handler_destroy(proc_handler_t *handler)
{
if (handler) {
for (size_t i = 0; i < handler->procs.num; i++)
proc_info_free(handler->procs.array + i);
da_free(handler->procs);
bfree(handler);
}
if (!handler)
return;
for (size_t i = 0; i < handler->procs.num; i++)
proc_info_free(handler->procs.array + i);
da_free(handler->procs);
pthread_mutex_destroy(&handler->mutex);
bfree(handler);
}
void proc_handler_add(proc_handler_t *handler, const char *decl_string,
@ -70,7 +97,18 @@ void proc_handler_add(proc_handler_t *handler, const char *decl_string,
pi.callback = proc;
pi.data = data;
da_push_back(handler->procs, &pi);
pthread_mutex_lock(&handler->mutex);
struct proc_info *existing = getproc(handler, pi.func.name);
if (existing) {
blog(LOG_WARNING, "Procedure '%s' already exists",
pi.func.name);
proc_info_free(&pi);
} else {
da_push_back(handler->procs, &pi);
}
pthread_mutex_unlock(&handler->mutex);
}
bool proc_handler_call(proc_handler_t *handler, const char *name,
@ -79,14 +117,16 @@ bool proc_handler_call(proc_handler_t *handler, const char *name,
if (!handler)
return false;
for (size_t i = 0; i < handler->procs.num; i++) {
struct proc_info *info = handler->procs.array + i;
pthread_mutex_lock(&handler->mutex);
struct proc_info *info = getproc(handler, name);
struct proc_info info_copy;
if (info)
info_copy = *info;
pthread_mutex_unlock(&handler->mutex);
if (strcmp(info->func.name, name) == 0) {
info->callback(info->data, params);
return true;
}
}
if (!info)
return false;
return false;
info_copy.callback(info_copy.data, params);
return true;
}