diff --git a/src/commands.c b/src/commands.c index 2cc4515..fb50052 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1326,6 +1326,16 @@ static bool set_or_get_value_helper(struct shell_variables *shell_state, sds *to parser *p = new_parser(l); program program = parse_program(p, false, false, NULL); + if(program == NULL || arrlen(program) == 0) { + printf("Error parsing new value: %s\n", new_value); + free_parser(p); + if(program) free_program(program); + free_lexer(l); + free_model_config(model_config); + sdsfree(var_name); + return false; + } + sds tmp1 = ast_to_string(a->assignment_stmt.value, &indentation_level); sds tmp2 = ast_to_string(program[0], &indentation_level); @@ -1580,9 +1590,9 @@ COMMAND_FUNCTION(unloadall) { } else { - for(int i = 0; i < len; i++) { - char *name = shell_state->loaded_models[i].key; - struct model_config *model_config = load_model_config_or_print_error(shell_state, tokens[0], name); + while(shlen(shell_state->loaded_models) > 0) { + char *name = shell_state->loaded_models[0].key; + struct model_config *model_config = shell_state->loaded_models[0].value; struct model_config **entries = hmget(shell_state->notify_entries, model_config->notify_code); arrfree(entries); @@ -1613,9 +1623,12 @@ COMMAND_FUNCTION(unload) { free_model_config(model_config); - if(shell_state->loaded_models != 0 && is_current) { - //TODO: do we want to know the last loaded model?? - shell_state->current_model = shell_state->loaded_models[0].value; + if(is_current) { + if(shlen(shell_state->loaded_models) > 0) { + shell_state->current_model = shell_state->loaded_models[0].value; + } else { + shell_state->current_model = NULL; + } } return true; diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 885fc2d..599ffdf 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -974,6 +974,11 @@ static void check_declaration(parser *p, ast *src) { } } + bool var_is_global = shgeti(p->global_scope, id_name) != -1; + if(var_is_global) { + src->assignment_stmt.name->identifier.global = true; + } + check_declaration(p, src->assignment_stmt.value); } break; case ast_ode_stmt: @@ -990,13 +995,9 @@ static void check_declaration(parser *p, ast *src) { num_return_values); } } - if(src->tag == ast_assignment_stmt) { - - bool var_is_global = shgeti(p->global_scope, src->assignment_stmt.name->identifier.value) != -1; - if(var_is_global) { - printf("%s is global\n", src->assignment_stmt.name->identifier.value); - src->assignment_stmt.name->identifier.global = true; - } + bool var_is_global = shgeti(p->global_scope, src->assignment_stmt.name->identifier.value) != -1; + if(var_is_global) { + src->assignment_stmt.name->identifier.global = true; } } break; diff --git a/src/inotify_helpers.c b/src/inotify_helpers.c index 94da1d1..a6b0903 100644 --- a/src/inotify_helpers.c +++ b/src/inotify_helpers.c @@ -3,9 +3,11 @@ #include "stb/stb_ds.h" #include #include +#include #include "commands.h" #include "inotify_helpers.h" +#include "file_utils/file_utils.h" void add_file_watch(struct shell_variables *shell_state, char *path) { //TODO: skip paths that have a watch already @@ -29,7 +31,53 @@ _Noreturn void *check_for_model_file_changes(void *args) { size_t i = 0; char ibuffer[BUF_LEN]; - size_t length = read(shell_state->fd_notify, ibuffer, BUF_LEN); + ssize_t length = read(shell_state->fd_notify, ibuffer, BUF_LEN); + + if(length < 0) { + if(errno == EINTR) { + continue; + } + + // Unrecoverable error: attempt to recreate the inotify descriptor and watches + if(shell_state->fd_notify >= 0) { + close(shell_state->fd_notify); + shell_state->fd_notify = -1; + } + + // Clear old notify entries + int n = hmlen(shell_state->notify_entries); + for(int j = 0; j < n; j++) { + arrfree(shell_state->notify_entries[j].value); + } + hmfree(shell_state->notify_entries); + shell_state->notify_entries = NULL; + + // Re-initialize inotify + int new_fd = inotify_init(); + if(new_fd < 0) { + sleep(1); + continue; + } + shell_state->fd_notify = new_fd; + + // Re-add watches for all currently loaded models + int n_models = shlen(shell_state->loaded_models); + for(int j = 0; j < n_models; j++) { + struct model_config *config = shell_state->loaded_models[j].value; + char *dir = get_dir_from_path(config->model_file); + if(dir) { + int wd = inotify_add_watch(shell_state->fd_notify, dir, IN_MODIFY|IN_MOVED_TO); + if(wd >= 0) { + struct model_config **entries = hmget(shell_state->notify_entries, wd); + config->notify_code = wd; + arrput(entries, config); + hmput(shell_state->notify_entries, wd, entries); + } + free(dir); + } + } + continue; + } while (i < length) {