fix a whole slew of memory leaks, and fix an internal ref mismatch
This commit is contained in:
parent
e3609b9ace
commit
c3a447d44f
@ -6,9 +6,12 @@ typedef void (*dc_cleanup_t)(void *);
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int ref;
|
int ref;
|
||||||
dc_cleanup_t cleanup;
|
dc_cleanup_t cleanup;
|
||||||
|
int debug;
|
||||||
} dc_refable_t;
|
} dc_refable_t;
|
||||||
|
|
||||||
void *dc_ref(void *);
|
void *dc_ref(void *);
|
||||||
void dc_unref(void *);
|
void dc_unref(void *);
|
||||||
|
|
||||||
|
void dc_ref_debug(void *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,12 +69,15 @@ dc_api_t dc_session_api(dc_session_t s);
|
|||||||
* access to the internal account cache
|
* access to the internal account cache
|
||||||
*/
|
*/
|
||||||
void dc_session_add_account(dc_session_t s, dc_account_t u);
|
void dc_session_add_account(dc_session_t s, dc_account_t u);
|
||||||
|
void dc_session_add_account_new(dc_session_t s, dc_account_t u);
|
||||||
dc_account_t dc_session_account_fullname(dc_session_t s, char const *f);
|
dc_account_t dc_session_account_fullname(dc_session_t s, char const *f);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new channel to the internal cache.
|
* Adds a new channel to the internal cache. _new does the same, but doesn't
|
||||||
|
* increase the reference count.
|
||||||
*/
|
*/
|
||||||
void dc_session_add_channel(dc_session_t s, dc_channel_t u);
|
void dc_session_add_channel(dc_session_t s, dc_channel_t u);
|
||||||
|
void dc_session_add_channel_new(dc_session_t s, dc_channel_t u);
|
||||||
|
|
||||||
dc_channel_t dc_session_channel_by_id(dc_session_t s, char const *snowflake);
|
dc_channel_t dc_session_channel_by_id(dc_session_t s, char const *snowflake);
|
||||||
|
|
||||||
@ -96,9 +99,11 @@ dc_channel_t dc_session_channel_recipients(dc_session_t s,
|
|||||||
dc_account_t *r, size_t sz);
|
dc_account_t *r, size_t sz);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a guild to be managed by this session.
|
* Add a guild to be managed by this session. _new does the same, but doesn't
|
||||||
|
* ref the given reference.
|
||||||
*/
|
*/
|
||||||
void dc_session_add_guild(dc_session_t s, dc_guild_t g);
|
void dc_session_add_guild(dc_session_t s, dc_guild_t g);
|
||||||
|
void dc_session_add_guild_new(dc_session_t s, dc_guild_t g);
|
||||||
GHashTable *dc_session_guilds(dc_session_t s);
|
GHashTable *dc_session_guilds(dc_session_t s);
|
||||||
dc_guild_t dc_session_guild_by_name(dc_session_t s, char const *name);
|
dc_guild_t dc_session_guild_by_name(dc_session_t s, char const *name);
|
||||||
|
|
||||||
|
@ -11,6 +11,12 @@ void *dc_ref(void *arg)
|
|||||||
ptr = (dc_refable_t *)arg;
|
ptr = (dc_refable_t *)arg;
|
||||||
++ptr->ref;
|
++ptr->ref;
|
||||||
|
|
||||||
|
if (ptr->debug) {
|
||||||
|
FILE *F = fopen("refdebug.txt", "a+");
|
||||||
|
fprintf(F, "libdc: ref inc: %p: %d\n", ptr, ptr->ref);
|
||||||
|
fclose(F);
|
||||||
|
}
|
||||||
|
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +27,33 @@ void dc_unref(void *arg)
|
|||||||
return_if_true(arg == NULL,);
|
return_if_true(arg == NULL,);
|
||||||
|
|
||||||
ptr = (dc_refable_t *)arg;
|
ptr = (dc_refable_t *)arg;
|
||||||
if ((--ptr->ref) <= 0 && ptr->cleanup != NULL) {
|
--ptr->ref;
|
||||||
|
|
||||||
|
if (ptr->debug) {
|
||||||
|
FILE *F = fopen("refdebug.txt", "a+");
|
||||||
|
fprintf(F, "libdc: ref dec: %p: %d\n",
|
||||||
|
ptr, ptr->ref
|
||||||
|
);
|
||||||
|
fclose(F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->ref <= 0 && ptr->cleanup != NULL) {
|
||||||
ptr->cleanup(arg);
|
ptr->cleanup(arg);
|
||||||
|
|
||||||
|
if (ptr->debug) {
|
||||||
|
FILE *F = fopen("refdebug.txt", "a+");
|
||||||
|
fprintf(F, "libdc: ref dec: %p: %d: cleanup!\n",
|
||||||
|
ptr, ptr->ref
|
||||||
|
);
|
||||||
|
fclose(F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dc_ref_debug(void *arg)
|
||||||
|
{
|
||||||
|
dc_refable_t *ptr = NULL;
|
||||||
|
return_if_true(arg == NULL,);
|
||||||
|
ptr = (dc_refable_t *)arg;
|
||||||
|
ptr->debug = true;
|
||||||
|
}
|
||||||
|
@ -83,7 +83,7 @@ static void dc_session_handle_ready(dc_session_t s, dc_event_t e)
|
|||||||
json_t *user = NULL;
|
json_t *user = NULL;
|
||||||
json_t *relationships = NULL;
|
json_t *relationships = NULL;
|
||||||
json_t *presences = NULL;
|
json_t *presences = NULL;
|
||||||
size_t idx = 0, i = 0;
|
size_t idx = 0;
|
||||||
json_t *c = NULL;
|
json_t *c = NULL;
|
||||||
json_t *channels = NULL;
|
json_t *channels = NULL;
|
||||||
json_t *guilds = NULL;
|
json_t *guilds = NULL;
|
||||||
@ -109,7 +109,7 @@ static void dc_session_handle_ready(dc_session_t s, dc_event_t e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_account_add_friend(s->login, u);
|
dc_account_add_friend(s->login, u);
|
||||||
dc_session_add_account(s, u);
|
dc_session_add_account_new(s, u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,14 +142,7 @@ static void dc_session_handle_ready(dc_session_t s, dc_event_t e)
|
|||||||
json_array_foreach(guilds, idx, c) {
|
json_array_foreach(guilds, idx, c) {
|
||||||
dc_guild_t guild = dc_guild_from_json(c);
|
dc_guild_t guild = dc_guild_from_json(c);
|
||||||
continue_if_true(guild == NULL);
|
continue_if_true(guild == NULL);
|
||||||
dc_session_add_guild(s, guild);
|
dc_session_add_guild_new(s, guild);
|
||||||
|
|
||||||
/* add their channels to our own thing
|
|
||||||
*/
|
|
||||||
for (i = 0; i < dc_guild_channels(guild); i++) {
|
|
||||||
dc_channel_t chan = dc_guild_nth_channel(guild, i);
|
|
||||||
dc_session_add_channel(s, chan);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,14 +152,10 @@ static void dc_session_handle_ready(dc_session_t s, dc_event_t e)
|
|||||||
if (channels != NULL && json_is_array(channels)) {
|
if (channels != NULL && json_is_array(channels)) {
|
||||||
json_array_foreach(channels, idx, c) {
|
json_array_foreach(channels, idx, c) {
|
||||||
dc_channel_t chan = dc_channel_from_json(c);
|
dc_channel_t chan = dc_channel_from_json(c);
|
||||||
if (chan == NULL) {
|
continue_if_true(chan == NULL);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: dedup recipients
|
/* TODO: dedup recipients
|
||||||
*/
|
*/
|
||||||
|
dc_session_add_channel_new(s, chan);
|
||||||
dc_session_add_channel(s, chan);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +238,18 @@ bool dc_session_logout(dc_session_t s)
|
|||||||
s->gateway = NULL;
|
s->gateway = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->accounts != NULL) {
|
||||||
|
g_hash_table_remove_all(s->accounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->guilds != NULL) {
|
||||||
|
g_hash_table_remove_all(s->guilds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->channels != NULL) {
|
||||||
|
g_hash_table_remove_all(s->channels);
|
||||||
|
}
|
||||||
|
|
||||||
s->ready = false;
|
s->ready = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -325,6 +326,12 @@ bool dc_session_equal_me_fullname(dc_session_t s, char const *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dc_session_add_account(dc_session_t s, dc_account_t u)
|
void dc_session_add_account(dc_session_t s, dc_account_t u)
|
||||||
|
{
|
||||||
|
return_if_true(s == NULL || u == NULL,);
|
||||||
|
dc_session_add_account_new(s, dc_ref(u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void dc_session_add_account_new(dc_session_t s, dc_account_t u)
|
||||||
{
|
{
|
||||||
return_if_true(s == NULL || u == NULL,);
|
return_if_true(s == NULL || u == NULL,);
|
||||||
return_if_true(dc_account_id(u) == NULL,);
|
return_if_true(dc_account_id(u) == NULL,);
|
||||||
@ -332,7 +339,7 @@ void dc_session_add_account(dc_session_t s, dc_account_t u)
|
|||||||
char const *id = dc_account_id(u);
|
char const *id = dc_account_id(u);
|
||||||
|
|
||||||
if (!g_hash_table_contains(s->accounts, id)) {
|
if (!g_hash_table_contains(s->accounts, id)) {
|
||||||
g_hash_table_insert(s->accounts, strdup(id), dc_ref(u));
|
g_hash_table_insert(s->accounts, strdup(id), u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,6 +369,12 @@ dc_channel_t dc_session_channel_by_id(dc_session_t s, char const *snowflake)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dc_session_add_channel(dc_session_t s, dc_channel_t u)
|
void dc_session_add_channel(dc_session_t s, dc_channel_t u)
|
||||||
|
{
|
||||||
|
return_if_true(s == NULL || u == NULL,);
|
||||||
|
dc_session_add_channel_new(s, dc_ref(u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void dc_session_add_channel_new(dc_session_t s, dc_channel_t u)
|
||||||
{
|
{
|
||||||
return_if_true(s == NULL || u == NULL,);
|
return_if_true(s == NULL || u == NULL,);
|
||||||
return_if_true(dc_channel_id(u) == NULL,);
|
return_if_true(dc_channel_id(u) == NULL,);
|
||||||
@ -369,7 +382,7 @@ void dc_session_add_channel(dc_session_t s, dc_channel_t u)
|
|||||||
char const *id = dc_channel_id(u);
|
char const *id = dc_channel_id(u);
|
||||||
|
|
||||||
if (!g_hash_table_contains(s->channels, id)) {
|
if (!g_hash_table_contains(s->channels, id)) {
|
||||||
g_hash_table_insert(s->channels, strdup(id), dc_ref(u));
|
g_hash_table_insert(s->channels, strdup(id), u);
|
||||||
/* TODO: dedup for saving storage
|
/* TODO: dedup for saving storage
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
@ -392,12 +405,7 @@ dc_channel_t dc_session_make_channel(dc_session_t s, dc_account_t *r,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return_if_true(c == NULL, NULL);
|
return_if_true(c == NULL, NULL);
|
||||||
dc_session_add_channel(s, c);
|
dc_session_add_channel_new(s, c);
|
||||||
/* unref once to match the proper ref count after
|
|
||||||
* dc_session_add_channel()
|
|
||||||
* BUG: if dc_session_add_channel() fails this is bad
|
|
||||||
*/
|
|
||||||
dc_unref(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc_channel_messages(c) <= 0 && dc_channel_is_dm(c)) {
|
if (dc_channel_messages(c) <= 0 && dc_channel_is_dm(c)) {
|
||||||
@ -453,17 +461,31 @@ GHashTable *dc_session_guilds(dc_session_t s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dc_session_add_guild(dc_session_t s, dc_guild_t g)
|
void dc_session_add_guild(dc_session_t s, dc_guild_t g)
|
||||||
|
{
|
||||||
|
return_if_true(s == NULL || g == NULL,);
|
||||||
|
dc_session_add_guild_new(s, dc_ref(g));
|
||||||
|
}
|
||||||
|
|
||||||
|
void dc_session_add_guild_new(dc_session_t s, dc_guild_t g)
|
||||||
{
|
{
|
||||||
return_if_true(s == NULL || g == NULL,);
|
return_if_true(s == NULL || g == NULL,);
|
||||||
return_if_true(dc_guild_id(g) == NULL,);
|
return_if_true(dc_guild_id(g) == NULL,);
|
||||||
|
|
||||||
char const *id = dc_guild_id(g);
|
char const *id = dc_guild_id(g);
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
if (!g_hash_table_contains(s->guilds, id)) {
|
if (!g_hash_table_contains(s->guilds, id)) {
|
||||||
g_hash_table_insert(s->guilds, strdup(id), dc_ref(g));
|
g_hash_table_insert(s->guilds, strdup(id), g);
|
||||||
/* TODO: dedup for saving storage
|
/* TODO: dedup for saving storage
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* add their channels to our own thing
|
||||||
|
*/
|
||||||
|
for (i = 0; i < dc_guild_channels(g); i++) {
|
||||||
|
dc_channel_t chan = dc_guild_nth_channel(g, i);
|
||||||
|
dc_session_add_channel(s, chan);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dc_guild_t dc_session_guild_by_name(dc_session_t s, char const *name)
|
dc_guild_t dc_session_guild_by_name(dc_session_t s, char const *name)
|
||||||
|
@ -50,9 +50,8 @@ bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac,
|
|||||||
dc_unref(current_session);
|
dc_unref(current_session);
|
||||||
current_session = dc_ref(s);
|
current_session = dc_ref(s);
|
||||||
|
|
||||||
LOG(n, L"login: %ls: authentication successful, waiting for ready from websocket...",
|
LOG(n, L"login: %ls: authentication successful, waiting for ready "
|
||||||
av[1]
|
L"from websocket...", av[1]);
|
||||||
);
|
|
||||||
|
|
||||||
while (!dc_session_is_ready(current_session))
|
while (!dc_session_is_ready(current_session))
|
||||||
;
|
;
|
||||||
|
@ -109,7 +109,7 @@ ncdc_mainwindow_t ncdc_mainwindow_new(void)
|
|||||||
ptr->focus = FOCUS_INPUT;
|
ptr->focus = FOCUS_INPUT;
|
||||||
ncdc_mainwindow_update_focus(ptr);
|
ncdc_mainwindow_update_focus(ptr);
|
||||||
|
|
||||||
return ptr;
|
return dc_ref(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -63,9 +63,7 @@ bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac,
|
|||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
||||||
dc_unref(c);
|
|
||||||
dc_unref(m);
|
dc_unref(m);
|
||||||
|
|
||||||
free(target);
|
free(target);
|
||||||
free(message);
|
free(message);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user