From 56938a0f1a535a45a267c7b54d57a279133c8c41 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 11 Jan 2018 16:20:14 +0300 Subject: [PATCH] DB: introduce a timeout handling caller info The upper bound is that if a function is called over 200 times then we don't use the caller_info. I ran into a situation in the kernel where a function was called exactly 200 times and it had about 200 states per call which meant that we loaded 40,000 into the cur_stree. It took about 6 minutes. So now I've decide that if loading the information takes longer than 10 seconds, I'm just going to bail on that. There are a bunch of unrelated clean up changes in this and I'm sorry for that... Signed-off-by: Dan Carpenter --- smatch_db.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/smatch_db.c b/smatch_db.c index e171ced9..76f54e13 100644 --- a/smatch_db.c +++ b/smatch_db.c @@ -547,17 +547,19 @@ void sql_select_call_implies(const char *cols, struct expression *call, struct select_caller_info_data { struct stree *final_states; + struct timeval start_time; int prev_func_id; int ignore; int results; }; +static int caller_info_callback(void *_data, int argc, char **argv, char **azColName); + static void sql_select_caller_info(struct select_caller_info_data *data, - const char *cols, struct symbol *sym, - int (*callback)(void*, int, char**, char**)) + const char *cols, struct symbol *sym) { if (__inline_fn) { - mem_sql(callback, data, + mem_sql(caller_info_callback, data, "select %s from caller_info where call_id = %lu;", cols, (unsigned long)__inline_fn); return; @@ -565,13 +567,13 @@ static void sql_select_caller_info(struct select_caller_info_data *data, if (sym->ident->name && is_common_function(sym->ident->name)) return; - run_sql(callback, data, + run_sql(caller_info_callback, data, "select %s from common_caller_info where %s order by call_id;", cols, get_static_filter(sym)); if (data->results) return; - run_sql(callback, data, + run_sql(caller_info_callback, data, "select %s from caller_info where %s order by call_id;", cols, get_static_filter(sym)); } @@ -905,12 +907,17 @@ static int caller_info_callback(void *_data, int argc, char **argv, char **azCol struct symbol *sym = NULL; struct def_callback *def_callback; struct stree *stree; + struct timeval cur_time; data->results = 1; if (argc != 5) return 0; + gettimeofday(&cur_time, NULL); + if (cur_time.tv_sec - data->start_time.tv_sec > 10) + return 0; + func_id = atoi(argv[0]); errno = 0; type = strtol(argv[1], NULL, 10); @@ -952,13 +959,6 @@ static int caller_info_callback(void *_data, int argc, char **argv, char **azCol return 0; } -static void get_direct_callers(struct select_caller_info_data *data, struct symbol *sym) -{ - sql_select_caller_info(data, - "call_id, type, parameter, key, value", sym, - caller_info_callback); -} - static struct string_list *ptr_names_done; static struct string_list *ptr_names; @@ -1012,10 +1012,13 @@ static void match_data_from_db(struct symbol *sym) struct select_caller_info_data data = { .prev_func_id = -1 }; struct sm_state *sm; struct stree *stree; + struct timeval end_time; if (!sym || !sym->ident) return; + gettimeofday(&data.start_time, NULL); + __push_fake_cur_stree(); __unnullify_path(); @@ -1035,7 +1038,10 @@ static void match_data_from_db(struct symbol *sym) return; } - get_direct_callers(&data, sym); + sql_select_caller_info(&data, + "call_id, type, parameter, key, value", + sym); + stree = __pop_fake_cur_stree(); if (!data.ignore) @@ -1072,7 +1078,9 @@ free_ptr_names: __free_ptr_list((struct ptr_list **)&ptr_names); __free_ptr_list((struct ptr_list **)&ptr_names_done); } else { - get_direct_callers(&data, sym); + sql_select_caller_info(&data, + "call_id, type, parameter, key, value", + sym); } stree = __pop_fake_cur_stree(); @@ -1080,9 +1088,12 @@ free_ptr_names: merge_stree(&data.final_states, stree); free_stree(&stree); - FOR_EACH_SM(data.final_states, sm) { - __set_sm(sm); - } END_FOR_EACH_SM(sm); + gettimeofday(&end_time, NULL); + if (end_time.tv_sec - data.start_time.tv_sec <= 10) { + FOR_EACH_SM(data.final_states, sm) { + __set_sm(sm); + } END_FOR_EACH_SM(sm); + } free_stree(&data.final_states); } -- 2.11.4.GIT