From 64a5fbf14e3f1e134e84340bc41b8b1e0788194a Mon Sep 17 00:00:00 2001 From: Nikos Gorogiannis Date: Fri, 4 Jun 2021 12:25:14 -0700 Subject: [PATCH] [biabduction] recognise restart exception in timeout handling Summary: Make the biabduction machinery for detecting (biabduction) exceptions that can be swallowed recognise the one thrown by the restart scheduler. The dependency hierarchy requires declaring that exception in `base`. Reviewed By: jvillard Differential Revision: D28773898 fbshipit-source-id: 2136346da --- infer/src/absint/AbstractInterpreter.ml | 2 +- infer/src/absint/TaskSchedulerTypes.ml | 4 ---- infer/src/backend/InferAnalyze.ml | 4 ++-- infer/src/backend/RestartScheduler.ml | 4 ++-- infer/src/backend/ondemand.ml | 2 +- infer/src/base/RestartSchedulerException.ml | 13 +++++++++++++ infer/src/base/RestartSchedulerException.mli | 14 ++++++++++++++ infer/src/base/SymOp.ml | 16 ++++++++++++---- infer/src/biabduction/Exceptions.ml | 10 +++++++--- 9 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 infer/src/base/RestartSchedulerException.ml create mode 100644 infer/src/base/RestartSchedulerException.mli diff --git a/infer/src/absint/AbstractInterpreter.ml b/infer/src/absint/AbstractInterpreter.ml index 31a4bfd58..354a5b1e3 100644 --- a/infer/src/absint/AbstractInterpreter.ml +++ b/infer/src/absint/AbstractInterpreter.ml @@ -328,7 +328,7 @@ module AbstractInterpreterCommon (TransferFunctions : NodeTransferFunctions) = s post | Error (exn, backtrace, instr) -> ( match exn with - | TaskSchedulerTypes.ProcnameAlreadyLocked _ -> + | RestartSchedulerException.ProcnameAlreadyLocked _ -> (* this isn't an error; don't log it *) () | _ -> diff --git a/infer/src/absint/TaskSchedulerTypes.ml b/infer/src/absint/TaskSchedulerTypes.ml index 836e87292..e5fe912a8 100644 --- a/infer/src/absint/TaskSchedulerTypes.ml +++ b/infer/src/absint/TaskSchedulerTypes.ml @@ -6,10 +6,6 @@ *) open! IStd -(** for the Restart scheduler: raise when a worker tries to analyze a procedure already being - analyzed by another process *) -exception ProcnameAlreadyLocked of {dependency_filename: string} - type target = | Procname of Procname.t | File of SourceFile.t diff --git a/infer/src/backend/InferAnalyze.ml b/infer/src/backend/InferAnalyze.ml index f8a61af53..c23355104 100644 --- a/infer/src/backend/InferAnalyze.ml +++ b/infer/src/backend/InferAnalyze.ml @@ -51,7 +51,7 @@ let analyze_target : (TaskSchedulerTypes.target, string) Tasks.doer = Ondemand.analyze_file exe_env source_file ; if Config.write_html then Printer.write_all_html_files source_file ; None - with TaskSchedulerTypes.ProcnameAlreadyLocked {dependency_filename} -> + with RestartSchedulerException.ProcnameAlreadyLocked {dependency_filename} -> Some dependency_filename ) in (* In call-graph scheduling, log progress every [per_procedure_logging_granularity] procedures. @@ -68,7 +68,7 @@ let analyze_target : (TaskSchedulerTypes.target, string) Tasks.doer = try Ondemand.analyze_proc_name_toplevel exe_env proc_name ; None - with TaskSchedulerTypes.ProcnameAlreadyLocked {dependency_filename} -> + with RestartSchedulerException.ProcnameAlreadyLocked {dependency_filename} -> Some dependency_filename in fun target -> diff --git a/infer/src/backend/RestartScheduler.ml b/infer/src/backend/RestartScheduler.ml index 3431c7826..037a96a2f 100644 --- a/infer/src/backend/RestartScheduler.ml +++ b/infer/src/backend/RestartScheduler.ml @@ -102,8 +102,8 @@ let lock_exn pname = else ( unlock_all () ; raise - (TaskSchedulerTypes.ProcnameAlreadyLocked {dependency_filename= Procname.to_filename pname}) - ) ) + (RestartSchedulerException.ProcnameAlreadyLocked + {dependency_filename= Procname.to_filename pname}) ) ) let unlock pname = diff --git a/infer/src/backend/ondemand.ml b/infer/src/backend/ondemand.ml index 97de31143..fa873eb43 100644 --- a/infer/src/backend/ondemand.ml +++ b/infer/src/backend/ondemand.ml @@ -221,7 +221,7 @@ let run_proc_analysis exe_env ~caller_pdesc callee_pdesc = let backtrace = Printexc.get_backtrace () in IExn.reraise_if exn ~f:(fun () -> match exn with - | TaskSchedulerTypes.ProcnameAlreadyLocked _ -> + | RestartSchedulerException.ProcnameAlreadyLocked _ -> clear_actives () ; restore_global_state old_state ; true diff --git a/infer/src/base/RestartSchedulerException.ml b/infer/src/base/RestartSchedulerException.ml new file mode 100644 index 000000000..1c6b1a86d --- /dev/null +++ b/infer/src/base/RestartSchedulerException.ml @@ -0,0 +1,13 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) +open! IStd + +(** for the Restart scheduler: raise when a worker tries to analyze a procedure already being + analyzed by another process *) +exception ProcnameAlreadyLocked of {dependency_filename: string} + +let is_not_restart_exception = function ProcnameAlreadyLocked _ -> false | _ -> true diff --git a/infer/src/base/RestartSchedulerException.mli b/infer/src/base/RestartSchedulerException.mli new file mode 100644 index 000000000..6acc0a28e --- /dev/null +++ b/infer/src/base/RestartSchedulerException.mli @@ -0,0 +1,14 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) +open! IStd + +(** for the Restart scheduler: raise when a worker tries to analyze a procedure already being + analyzed by another process *) +exception ProcnameAlreadyLocked of {dependency_filename: string} + +val is_not_restart_exception : exn -> bool +(** check if the exception passed is the one defined above *) diff --git a/infer/src/base/SymOp.ml b/infer/src/base/SymOp.ml index 11e85249d..5c9f36a70 100644 --- a/infer/src/base/SymOp.ml +++ b/infer/src/base/SymOp.ml @@ -20,7 +20,12 @@ type failure_kind = (** failure that prevented analysis from finishing *) exception Analysis_failure_exe of failure_kind -let exn_not_failure = function Analysis_failure_exe _ -> false | _ -> true +let exn_not_failure = function + | Analysis_failure_exe _ | RestartSchedulerException.ProcnameAlreadyLocked _ -> + false + | _ -> + true + let try_finally ~f ~finally = match f () with @@ -29,14 +34,17 @@ let try_finally ~f ~finally = r | exception (Analysis_failure_exe _ as f_exn) -> IExn.reraise_after f_exn ~f:(fun () -> - try finally () with _ -> (* swallow in favor of the original exception *) () ) - | exception f_exn -> + try finally () + with finally_exn when RestartSchedulerException.is_not_restart_exception finally_exn -> + (* swallow in favor of the original exception unless it's the restart scheduler exception *) + () ) + | exception f_exn when RestartSchedulerException.is_not_restart_exception f_exn -> IExn.reraise_after f_exn ~f:(fun () -> try finally () with | finally_exn when (* do not swallow Analysis_failure_exe thrown from finally *) - match finally_exn with Analysis_failure_exe _ -> false | _ -> true + exn_not_failure finally_exn -> () ) diff --git a/infer/src/biabduction/Exceptions.ml b/infer/src/biabduction/Exceptions.ml index 5470999d9..a6cdc6b1f 100644 --- a/infer/src/biabduction/Exceptions.ml +++ b/infer/src/biabduction/Exceptions.ml @@ -194,6 +194,10 @@ let print_exception_html s exn = (** Return true if the exception is not serious and should be handled in timeout mode *) let handle_exception exn = - let error = recognize_exception exn in - IssueType.equal_visibility error.issue_type.visibility User - || IssueType.equal_visibility error.issue_type.visibility Developer + match exn with + | RestartSchedulerException.ProcnameAlreadyLocked _ -> + false + | _ -> + let error = recognize_exception exn in + IssueType.equal_visibility error.issue_type.visibility User + || IssueType.equal_visibility error.issue_type.visibility Developer