Quick fix for thread handle leak; project parse crash bug fix

master
Allen Webster 2020-05-01 07:38:57 -07:00
parent 5561704e2e
commit 63bfed7ab1
11 changed files with 146 additions and 73 deletions

30
4ed.cpp
View File

@ -746,6 +746,36 @@ App_Step_Sig(app_step){
end_render_section(target);
}
// TODO(allen): This is dumb. Let's rethink view cleanup strategy.
// NOTE(allen): wind down coroutines
for (;;){
Model_Wind_Down_Co *node = models->wind_down_stack;
if (node == 0){
break;
}
sll_stack_pop(models->wind_down_stack);
Coroutine *co = node->co;
for (i32 j = 0; co != 0; j += 1){
Co_In in = {};
in.user_input.abort = true;
Co_Out ignore = {};
co = co_run(tctx, models, co, &in, &ignore);
if (j == 100){
Application_Links app = {};
app.tctx = tctx;
app.cmd_context = models;
#define M "SERIOUS ERROR: coroutine wind down did not complete"
print_message(&app, string_u8_litexpr(M));
#undef M
break;
}
}
sll_stack_push(models->free_wind_downs, node);
}
// NOTE(allen): flush the log
log_flush(tctx, models);

View File

@ -33,58 +33,6 @@ file_cursor_to_end(Thread_Context *tctx, Models *models, Editing_File *file){
}
}
function void
models_push_view_command_function(Models *models, View_ID view_id, Custom_Command_Function *custom_func){
Model_View_Command_Function *node = models->free_view_cmd_funcs;
if (node == 0){
node = push_array(models->arena, Model_View_Command_Function, 1);
}
else{
sll_stack_pop(models->free_view_cmd_funcs);
}
sll_queue_push(models->first_view_cmd_func, models->last_view_cmd_func, node);
node->view_id = view_id;
node->custom_func = custom_func;
}
function Model_View_Command_Function
models_pop_view_command_function(Models *models){
Model_View_Command_Function result = {};
if (models->first_view_cmd_func != 0){
Model_View_Command_Function *node = models->first_view_cmd_func;
result.custom_func = node->custom_func;
result.view_id = node->view_id;
sll_queue_pop(models->first_view_cmd_func, models->last_view_cmd_func);
sll_stack_push(models->free_view_cmd_funcs, node);
}
return(result);
}
function void
models_push_virtual_event(Models *models, Input_Event *event){
Model_Input_Event_Node *node = models->free_virtual_event;
if (node == 0){
node = push_array(&models->virtual_event_arena, Model_Input_Event_Node, 1);
}
else{
sll_stack_pop(models->free_virtual_event);
}
sll_queue_push(models->first_virtual_event, models->last_virtual_event, node);
node->event = copy_input_event(&models->virtual_event_arena, event);
}
function Input_Event
models_pop_virtual_event(Arena *arena, Models *models){
Input_Event result = {};
if (models->first_virtual_event != 0){
Model_Input_Event_Node *node = models->first_virtual_event;
result = copy_input_event(arena, &node->event);
sll_queue_pop(models->first_virtual_event, models->last_virtual_event);
sll_stack_push(models->free_virtual_event, node);
}
return(result);
}
////////////////////////////////
function b32

77
4ed_app_models.cpp Normal file
View File

@ -0,0 +1,77 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 01.05.2020
*
* Implementation of the root models features.
*
*/
// TOP
function void
models_push_view_command_function(Models *models, View_ID view_id, Custom_Command_Function *custom_func){
Model_View_Command_Function *node = models->free_view_cmd_funcs;
if (node == 0){
node = push_array(models->arena, Model_View_Command_Function, 1);
}
else{
sll_stack_pop(models->free_view_cmd_funcs);
}
sll_queue_push(models->first_view_cmd_func, models->last_view_cmd_func, node);
node->view_id = view_id;
node->custom_func = custom_func;
}
function Model_View_Command_Function
models_pop_view_command_function(Models *models){
Model_View_Command_Function result = {};
if (models->first_view_cmd_func != 0){
Model_View_Command_Function *node = models->first_view_cmd_func;
result.custom_func = node->custom_func;
result.view_id = node->view_id;
sll_queue_pop(models->first_view_cmd_func, models->last_view_cmd_func);
sll_stack_push(models->free_view_cmd_funcs, node);
}
return(result);
}
function void
models_push_virtual_event(Models *models, Input_Event *event){
Model_Input_Event_Node *node = models->free_virtual_event;
if (node == 0){
node = push_array(&models->virtual_event_arena, Model_Input_Event_Node, 1);
}
else{
sll_stack_pop(models->free_virtual_event);
}
sll_queue_push(models->first_virtual_event, models->last_virtual_event, node);
node->event = copy_input_event(&models->virtual_event_arena, event);
}
function Input_Event
models_pop_virtual_event(Arena *arena, Models *models){
Input_Event result = {};
if (models->first_virtual_event != 0){
Model_Input_Event_Node *node = models->first_virtual_event;
result = copy_input_event(arena, &node->event);
sll_queue_pop(models->first_virtual_event, models->last_virtual_event);
sll_stack_push(models->free_virtual_event, node);
}
return(result);
}
function void
models_push_wind_down(Models *models, Coroutine *co){
Model_Wind_Down_Co *node = models->free_wind_downs;
if (node != 0){
sll_stack_pop(models->free_wind_downs);
}
else{
node = push_array(models->arena, Model_Wind_Down_Co, 1);
}
sll_stack_push(models->wind_down_stack, node);
node->co = co;
}
// BOTTOM

View File

@ -44,6 +44,11 @@ struct Model_Input_Event_Node{
Input_Event event;
};
struct Model_Wind_Down_Co{
Model_Wind_Down_Co *next;
Coroutine *co;
};
struct Models{
Arena arena_;
Arena *arena;
@ -55,6 +60,8 @@ struct Models{
Face_ID global_face_id;
Coroutine_Group coroutines;
Model_Wind_Down_Co *wind_down_stack;
Model_Wind_Down_Co *free_wind_downs;
Child_Process_Container child_processes;
Custom_API config_api;

View File

@ -108,6 +108,7 @@
#include "4ed_font_set.cpp"
#include "4ed_translation.cpp"
#include "4ed_render_target.cpp"
#include "4ed_app_models.cpp"
#include "4ed_buffer.cpp"
#include "4ed_string_matching.cpp"
#include "4ed_history.cpp"

View File

@ -591,11 +591,16 @@ view_init(Thread_Context *tctx, Models *models, View *view, Editing_File *initia
Assert(view->co != 0);
}
// TODO(allen): This doesn't make any sense!!!!!! COROUTINE SHUTDOWN? VIEW CLOSING? WADAFUQ?
function b32
view_close(Models *models, View *view){
Layout *layout = &models->layout;
b32 result = false;
if (layout_close_panel(layout, view->panel)){
if (view->co != 0){
models_push_wind_down(models, view->co);
}
live_set_free_view(&models->lifetime_allocator, &models->view_set, view);
result = true;
}
@ -614,6 +619,8 @@ view_check_co_exited(Models *models, View *view){
}
}
// TODO(allen): This is dumb. Let's rethink view cleanup strategy.
internal void
co_single_abort(Thread_Context *tctx, Models *models, View *view){
Coroutine *co = view->co;

View File

@ -944,7 +944,7 @@ function b32
config_compound_compound_member(Config *config, Config_Compound *compound,
String_Const_u8 var_name, i32 index, Config_Compound** var_out){
Config_Get_Result result = config_compound_member(config, compound, var_name, index);
b32 success = result.success && result.type == ConfigRValueType_Compound;
b32 success = (result.success && result.type == ConfigRValueType_Compound);
if (success){
*var_out = result.compound;
}

View File

@ -892,7 +892,6 @@ BUFFER_HOOK_SIG(default_file_save){
b32 is_virtual = global_config.enable_virtual_whitespace;
if (global_config.automatically_indent_text_on_save && is_virtual){
clean_all_lines_buffer(app, buffer_id);
auto_indent_buffer(app, buffer_id, buffer_range(app, buffer_id));
}

View File

@ -332,9 +332,8 @@ parse_project__config_data__version_1(Application_Links *app, Arena *arena, Stri
goto finish_command;
}
cmd_result = config_compound_member(parsed, src,
string_u8_litexpr("cmd"), 1);
if (cmd_result.success){
cmd_result = config_compound_member(parsed, src, string_u8_litexpr("cmd"), 1);
if (cmd_result.success && cmd_result.type == ConfigRValueType_Compound){
cmd_set = cmd_result.compound;
cmd_pos = cmd_result.pos;
}
@ -691,18 +690,21 @@ set_current_project(Application_Links *app, Project *project, Config *parsed){
if (print_feedback){
Temp_Memory temp = begin_temp(scratch);
// Top
print_message(app, string_u8_litexpr("Loaded project file:\n"));
// Errors
String_Const_u8 error_text = config_stringize_errors(app, scratch, parsed);
if (error_text.size > 0){
print_message(app, string_u8_litexpr("Project errors:\n"));
print_message(app, error_text);
print_message(app, string_u8_litexpr("\n"));
}
// Values
if (project == 0){
print_message(app, string_u8_litexpr("Could not instantiate project\n"));
}
else{
print_message(app, string_u8_litexpr("New project contents:\n"));
Temp_Memory temp2 = begin_temp(scratch);
List_String_Const_u8 list = {};

View File

@ -287,7 +287,7 @@ static Command_Metadata fcoder_metacmd_table[243] = {
{ PROC_LINKS(click_set_cursor_if_lbutton, 0), false, "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 241 },
{ PROC_LINKS(click_set_mark, 0), false, "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 253 },
{ PROC_LINKS(clipboard_record_clip, 0), false, "clipboard_record_clip", 21, "In response to a new clipboard contents events, saves the new clip onto the clipboard history", 93, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 7 },
{ PROC_LINKS(close_all_code, 0), false, "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 842 },
{ PROC_LINKS(close_all_code, 0), false, "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 844 },
{ PROC_LINKS(close_build_panel, 0), false, "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 174 },
{ PROC_LINKS(close_panel, 0), false, "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 653 },
{ PROC_LINKS(command_documentation, 0), true, "command_documentation", 21, "Prompts the user to select a command then loads a doc buffer for that item", 74, "w:\\4ed\\code\\custom\\4coder_docs.cpp", 34, 190 },
@ -360,7 +360,7 @@ static Command_Metadata fcoder_metacmd_table[243] = {
{ PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), false, "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 221 },
{ PROC_LINKS(list_all_substring_locations, 0), false, "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 171 },
{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), false, "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 183 },
{ PROC_LINKS(load_project, 0), false, "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 862 },
{ PROC_LINKS(load_project, 0), false, "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 864 },
{ PROC_LINKS(load_theme_current_buffer, 0), false, "load_theme_current_buffer", 25, "Parse the current buffer as a theme file and add the theme to the theme list. If the buffer has a .4coder postfix in it's name, it is removed when the name is saved.", 165, "w:\\4ed\\code\\custom\\4coder_config.cpp", 36, 1627 },
{ PROC_LINKS(load_themes_default_folder, 0), false, "load_themes_default_folder", 26, "Loads all the theme files in the default theme folder.", 54, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 457 },
{ PROC_LINKS(load_themes_hot_directory, 0), false, "load_themes_hot_directory", 25, "Loads all the theme files in the current hot directory.", 55, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 469 },
@ -401,8 +401,8 @@ static Command_Metadata fcoder_metacmd_table[243] = {
{ PROC_LINKS(multi_paste, 0), false, "multi_paste", 11, "Paste multiple entries from the clipboard at once", 49, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 224 },
{ PROC_LINKS(multi_paste_interactive, 0), false, "multi_paste_interactive", 23, "Paste multiple lines from the clipboard history, controlled with arrow keys", 75, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 366 },
{ PROC_LINKS(multi_paste_interactive_quick, 0), false, "multi_paste_interactive_quick", 29, "Paste multiple lines from the clipboard history, controlled by inputing the number of lines to paste", 100, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 375 },
{ PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 848 },
{ PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 854 },
{ PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 850 },
{ PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 856 },
{ PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1558 },
{ PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1889 },
{ PROC_LINKS(open_long_braces, 0), false, "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 46 },
@ -423,9 +423,9 @@ static Command_Metadata fcoder_metacmd_table[243] = {
{ PROC_LINKS(profile_disable, 0), false, "profile_disable", 15, "Prevent 4coder's self profiler from gathering new profiling information.", 72, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 219 },
{ PROC_LINKS(profile_enable, 0), false, "profile_enable", 14, "Allow 4coder's self profiler to gather new profiling information.", 65, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 212 },
{ PROC_LINKS(profile_inspect, 0), true, "profile_inspect", 15, "Inspect all currently collected profiling information in 4coder's self profiler.", 80, "w:\\4ed\\code\\custom\\4coder_profile_inspect.cpp", 45, 886 },
{ PROC_LINKS(project_command_lister, 0), false, "project_command_lister", 22, "Open a lister of all commands in the currently loaded project.", 62, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1288 },
{ PROC_LINKS(project_fkey_command, 0), false, "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 870 },
{ PROC_LINKS(project_go_to_root_directory, 0), false, "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 896 },
{ PROC_LINKS(project_command_lister, 0), false, "project_command_lister", 22, "Open a lister of all commands in the currently loaded project.", 62, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1290 },
{ PROC_LINKS(project_fkey_command, 0), false, "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 872 },
{ PROC_LINKS(project_go_to_root_directory, 0), false, "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 898 },
{ PROC_LINKS(query_replace, 0), false, "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1249 },
{ PROC_LINKS(query_replace_identifier, 0), false, "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1270 },
{ PROC_LINKS(query_replace_selection, 0), false, "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1286 },
@ -463,10 +463,10 @@ static Command_Metadata fcoder_metacmd_table[243] = {
{ PROC_LINKS(set_mark, 0), false, "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 115 },
{ PROC_LINKS(set_mode_to_notepad_like, 0), false, "set_mode_to_notepad_like", 24, "Sets the edit mode to Notepad like.", 35, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 427 },
{ PROC_LINKS(set_mode_to_original, 0), false, "set_mode_to_original", 20, "Sets the edit mode to 4coder original.", 38, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 421 },
{ PROC_LINKS(setup_build_bat, 0), false, "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1237 },
{ PROC_LINKS(setup_build_bat_and_sh, 0), false, "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1249 },
{ PROC_LINKS(setup_build_sh, 0), false, "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1243 },
{ PROC_LINKS(setup_new_project, 0), false, "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1230 },
{ PROC_LINKS(setup_build_bat, 0), false, "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1239 },
{ PROC_LINKS(setup_build_bat_and_sh, 0), false, "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1251 },
{ PROC_LINKS(setup_build_sh, 0), false, "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1245 },
{ PROC_LINKS(setup_new_project, 0), false, "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1232 },
{ PROC_LINKS(show_filebar, 0), false, "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 676 },
{ PROC_LINKS(show_scrollbar, 0), false, "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 662 },
{ PROC_LINKS(show_the_log_graph, 0), true, "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 993 },

View File

@ -5,7 +5,9 @@
+ Fix: when generated/metadata* files are missing buildsuper still succeeds
+ Fix: mac does not hang opening multiple files
+ Fix: line number margin performance
+ Fix: crash in notepade like mode when replacing a highlighted range in a parsed file
+ Fix: no crash in notepade like mode when replacing a highlighted range in a parsed file
+ Fix: no thread handle leak when closing a view
+ Fix: no crash when a project file .cmd is not the right type
4.1.4
+ MAJOR: The clipboard history is now a fully custom layer implemented system. Users maintaining a customization layer should try to update their call sites to the old clipboard API. #define FCODER_TRANSITION_TO 4001004 to disable the transitional function wrappers when you are ready to make the transition.