mirror of https://github.com/bjornbytes/lovr.git
Fix Channel memory leak;
Channels need to be removed from the global array/map when destroyed. Note that this exposes an infinite loop in map_remove, which will be fixed later. Note also that Channel's are retained if they have any messages in them, to prevent releasing a channel while it has pending messages.
This commit is contained in:
parent
8d12f0b867
commit
13136482b9
|
@ -80,6 +80,7 @@ static int l_lovrThreadGetChannel(lua_State* L) {
|
|||
const char* name = luaL_checkstring(L, 1);
|
||||
Channel* channel = lovrThreadGetChannel(name);
|
||||
luax_pushtype(L, Channel, channel);
|
||||
lovrRelease(Channel, channel);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,18 +15,22 @@ struct Channel {
|
|||
size_t head;
|
||||
uint64_t sent;
|
||||
uint64_t received;
|
||||
uint64_t hash;
|
||||
};
|
||||
|
||||
Channel* lovrChannelCreate(void) {
|
||||
Channel* lovrChannelCreate(uint64_t hash) {
|
||||
Channel* channel = lovrAlloc(Channel);
|
||||
arr_init(&channel->messages);
|
||||
mtx_init(&channel->lock, mtx_plain | mtx_timed);
|
||||
cnd_init(&channel->cond);
|
||||
channel->hash = hash;
|
||||
return channel;
|
||||
}
|
||||
|
||||
extern void lovrThreadRemoveChannel(uint64_t hash);
|
||||
void lovrChannelDestroy(void* ref) {
|
||||
Channel* channel = ref;
|
||||
lovrThreadRemoveChannel(channel->hash);
|
||||
lovrChannelClear(channel);
|
||||
arr_free(&channel->messages);
|
||||
mtx_destroy(&channel->lock);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
struct Variant;
|
||||
|
||||
typedef struct Channel Channel;
|
||||
Channel* lovrChannelCreate(void);
|
||||
Channel* lovrChannelCreate(uint64_t hash);
|
||||
void lovrChannelDestroy(void* ref);
|
||||
bool lovrChannelPush(Channel* channel, struct Variant* variant, double timeout, uint64_t* id);
|
||||
bool lovrChannelPop(Channel* channel, struct Variant* variant, double timeout);
|
||||
|
|
|
@ -38,12 +38,23 @@ Channel* lovrThreadGetChannel(const char* name) {
|
|||
if (index == MAP_NIL) {
|
||||
index = state.channels.length;
|
||||
map_set(&state.channelMap, hash, index);
|
||||
arr_push(&state.channels, lovrChannelCreate());
|
||||
arr_push(&state.channels, lovrChannelCreate(hash));
|
||||
}
|
||||
|
||||
return state.channels.data[index];
|
||||
}
|
||||
|
||||
void lovrThreadRemoveChannel(uint64_t hash) {
|
||||
uint64_t index = map_get(&state.channelMap, hash);
|
||||
|
||||
if (index == MAP_NIL) {
|
||||
return;
|
||||
}
|
||||
|
||||
map_remove(&state.channelMap, hash);
|
||||
arr_splice(&state.channels, index, 1);
|
||||
}
|
||||
|
||||
Thread* lovrThreadInit(Thread* thread, int (*runner)(void*), Blob* body) {
|
||||
lovrRetain(body);
|
||||
thread->runner = runner;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "data/blob.h"
|
||||
#include "lib/tinycthread/tinycthread.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -18,6 +19,7 @@ typedef struct Thread {
|
|||
bool lovrThreadModuleInit(void);
|
||||
void lovrThreadModuleDestroy(void);
|
||||
struct Channel* lovrThreadGetChannel(const char* name);
|
||||
void lovrThreadRemoveChannel(uint64_t hash);
|
||||
|
||||
Thread* lovrThreadInit(Thread* thread, int (*runner)(void*), Blob* body);
|
||||
#define lovrThreadCreate(...) lovrThreadInit(lovrAlloc(Thread), __VA_ARGS__)
|
||||
|
|
Loading…
Reference in New Issue