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 { | ||||
|     int ref; | ||||
|     dc_cleanup_t cleanup; | ||||
|     int debug; | ||||
| } dc_refable_t; | ||||
| 
 | ||||
| void *dc_ref(void *); | ||||
| void dc_unref(void *); | ||||
| 
 | ||||
| void dc_ref_debug(void *); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -69,12 +69,15 @@ dc_api_t dc_session_api(dc_session_t s); | ||||
|  * access to the internal account cache | ||||
|  */ | ||||
| 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); | ||||
| 
 | ||||
| /**
 | ||||
|  * 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_new(dc_session_t s, dc_channel_t u); | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
| /**
 | ||||
|  * 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_new(dc_session_t s, dc_guild_t g); | ||||
| GHashTable *dc_session_guilds(dc_session_t s); | ||||
| 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->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; | ||||
| } | ||||
| 
 | ||||
| @ -21,7 +27,33 @@ void dc_unref(void *arg) | ||||
|     return_if_true(arg == NULL,); | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|         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 *relationships = NULL; | ||||
|     json_t *presences = NULL; | ||||
|     size_t idx = 0, i = 0; | ||||
|     size_t idx = 0; | ||||
|     json_t *c = NULL; | ||||
|     json_t *channels = 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_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) { | ||||
|             dc_guild_t guild = dc_guild_from_json(c); | ||||
|             continue_if_true(guild == NULL); | ||||
|             dc_session_add_guild(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); | ||||
|             } | ||||
|             dc_session_add_guild_new(s, guild); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -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)) { | ||||
|         json_array_foreach(channels, idx, c) { | ||||
|             dc_channel_t chan = dc_channel_from_json(c); | ||||
|             if (chan == NULL) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             continue_if_true(chan == NULL); | ||||
|             /* TODO: dedup recipients
 | ||||
|              */ | ||||
| 
 | ||||
|             dc_session_add_channel(s, chan); | ||||
|             dc_session_add_channel_new(s, chan); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -249,6 +238,18 @@ bool dc_session_logout(dc_session_t s) | ||||
|         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; | ||||
| 
 | ||||
|     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) | ||||
| { | ||||
|     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(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); | ||||
| 
 | ||||
|     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) | ||||
| { | ||||
|     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(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); | ||||
| 
 | ||||
|     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
 | ||||
|          */ | ||||
|     } | ||||
| @ -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); | ||||
|         dc_session_add_channel(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); | ||||
|         dc_session_add_channel_new(s, 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) | ||||
| { | ||||
|     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(dc_guild_id(g) == NULL,); | ||||
| 
 | ||||
|     char const *id = dc_guild_id(g); | ||||
|     size_t i = 0; | ||||
| 
 | ||||
|     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
 | ||||
|          */ | ||||
|     } | ||||
| 
 | ||||
|     /* 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) | ||||
|  | ||||
| @ -50,9 +50,8 @@ bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac, | ||||
|     dc_unref(current_session); | ||||
|     current_session = dc_ref(s); | ||||
| 
 | ||||
|     LOG(n, L"login: %ls: authentication successful, waiting for ready from websocket...", | ||||
|         av[1] | ||||
|         ); | ||||
|     LOG(n, L"login: %ls: authentication successful, waiting for ready " | ||||
|         L"from websocket...", av[1]); | ||||
| 
 | ||||
|     while (!dc_session_is_ready(current_session)) | ||||
|         ; | ||||
|  | ||||
| @ -109,7 +109,7 @@ ncdc_mainwindow_t ncdc_mainwindow_new(void) | ||||
|     ptr->focus = FOCUS_INPUT; | ||||
|     ncdc_mainwindow_update_focus(ptr); | ||||
| 
 | ||||
|     return ptr; | ||||
|     return dc_ref(ptr); | ||||
| } | ||||
| 
 | ||||
| static bool | ||||
|  | ||||
| @ -63,9 +63,7 @@ bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, | ||||
| 
 | ||||
| cleanup: | ||||
| 
 | ||||
|     dc_unref(c); | ||||
|     dc_unref(m); | ||||
| 
 | ||||
|     free(target); | ||||
|     free(message); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user