xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
Commit e3e16ec7d163bb6dc9cf7354c6ba9e7215e706db

Cleaner deletion of key chunks
Move freeing data managed by the chunk from free_tree() to
free_chunk_data() to not have a chunk half-freed after deletion is
postponed and to have type-specific cleanup code in one place.
Author: xaizek
Author date (UTC): 2025-06-13 12:51
Committer name: xaizek
Committer date (UTC): 2025-06-14 08:35
Parent(s): 877bf90447445509c1033c76eadc623f0d7d3db1
Signing key: 99DC5E4DB05F6BE2
Tree: cc4818558d4c43732f179b3dad689e693eb943a5
File Lines added Lines deleted
src/engine/keys.c 22 19
File src/engine/keys.c changed (mode: 100644) (index 621055817..b40db994d)
... ... static void remove_foreign_in_forest(key_chunk_t *forest, size_t size);
108 108 static void free_forest(key_chunk_t *forest, size_t size); static void free_forest(key_chunk_t *forest, size_t size);
109 109 static void free_tree(key_chunk_t *root); static void free_tree(key_chunk_t *root);
110 110 static void free_chunk(key_chunk_t *chunk); static void free_chunk(key_chunk_t *chunk);
111 static void free_chunk_data(key_chunk_t *chunk);
111 112 static int execute_keys_general_wrapper(const wchar_t keys[], int timed_out, static int execute_keys_general_wrapper(const wchar_t keys[], int timed_out,
112 113 int mapped, int no_remap); int mapped, int no_remap);
113 114 static int execute_keys_general(const wchar_t keys[], int timed_out, int mapped, static int execute_keys_general(const wchar_t keys[], int timed_out, int mapped,
 
... ... free_forest(key_chunk_t *forest, size_t size)
263 264 free(forest); free(forest);
264 265 } }
265 266
267 /* Frees memory used by a specific chunk and all of its children except those
268 * which are still in use in which case their deletion is postponed. */
266 269 static void static void
267 270 free_tree(key_chunk_t *root) free_tree(key_chunk_t *root)
268 271 { {
 
... ... free_tree(key_chunk_t *root)
277 280 free_tree(root->next); free_tree(root->next);
278 281 free_chunk(root->next); free_chunk(root->next);
279 282 } }
280
281 if(root->type == USER_CMD)
282 {
283 free(root->conf.data.cmd);
284 }
285 283 } }
286 284
285 /* Frees memory of a specific chunk unless it's still in use in which case its
286 * deletion is postponed. */
287 287 static void static void
288 288 free_chunk(key_chunk_t *chunk) free_chunk(key_chunk_t *chunk)
289 289 { {
290 if(chunk->enters == 0)
290 if(chunk->enters != 0)
291 291 { {
292 free(chunk);
292 chunk->deleted = 1;
293 return;
293 294 } }
294 else
295
296 free_chunk_data(chunk);
297 free(chunk);
298 }
299
300 /* Frees data referenced by the chunk without freeing the chunk itself. */
301 static void
302 free_chunk_data(key_chunk_t *chunk)
303 {
304 if(chunk->type == USER_CMD)
295 305 { {
296 chunk->deleted = 1;
306 free(chunk->conf.data.cmd);
297 307 } }
298 308 } }
299 309
 
... ... leave_chunk(key_chunk_t *chunk)
899 909 { {
900 910 /* Removal of the chunk was postponed because it was in use, proceed with /* Removal of the chunk was postponed because it was in use, proceed with
901 911 * this now. */ * this now. */
902 free(chunk);
912 free_chunk(chunk);
903 913 } }
904 914 } }
905 915
 
... ... find_keys(key_chunk_t *root, const wchar_t keys[])
1081 1091 static void static void
1082 1092 remove_chunk(key_chunk_t *chunk) remove_chunk(key_chunk_t *chunk)
1083 1093 { {
1084 if(chunk->type == USER_CMD)
1085 {
1086 free(chunk->conf.data.cmd);
1087 }
1088
1094 free_chunk_data(chunk);
1089 1095 chunk->type = BUILTIN_WAIT_POINT; chunk->type = BUILTIN_WAIT_POINT;
1090 1096 chunk->conf.data.handler = NULL; chunk->conf.data.handler = NULL;
1091 1097
 
... ... add_keys_inner(key_chunk_t *root, const wchar_t *keys)
1216 1222
1217 1223 /* Reset most of the fields of a previously existing key before returning /* Reset most of the fields of a previously existing key before returning
1218 1224 * it. */ * it. */
1219 if(curr->type == USER_CMD)
1220 {
1221 free(curr->conf.data.cmd);
1222 }
1225 free_chunk_data(curr);
1223 1226 init_chunk_data(curr, curr->key, BUILTIN_KEYS); init_chunk_data(curr, curr->key, BUILTIN_KEYS);
1224 1227
1225 1228 return curr; return curr;
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master