diff --git a/infer/src/concurrency/starvation.ml b/infer/src/concurrency/starvation.ml index f81dc7222..6814c8764 100644 --- a/infer/src/concurrency/starvation.ml +++ b/infer/src/concurrency/starvation.ml @@ -70,8 +70,8 @@ module TransferFunctions (CFG : ProcCfg.S) = struct None in match instr with - | Call (_, Direct callee_pname, actuals, _, loc) -> ( - match Models.get_lock callee_pname actuals with + | Call (_, Direct callee, actuals, _, loc) -> ( + match Models.get_lock callee actuals with | Lock -> get_path actuals |> Option.value_map ~default:astate ~f:(Domain.acquire astate loc) | Unlock -> @@ -80,15 +80,16 @@ module TransferFunctions (CFG : ProcCfg.S) = struct astate | NoEffect -> if - Models.is_countdownlatch_await callee_pname - || Models.is_two_way_binder_transact tenv actuals callee_pname - || Models.is_blocking_java_io tenv callee_pname - then Domain.blocking_call callee_pname loc astate - else if is_on_main_thread callee_pname then Domain.set_on_main_thread astate + Models.is_countdownlatch_await callee + || Models.is_two_way_binder_transact tenv actuals callee + || Models.is_blocking_java_io tenv callee + then + let caller = Procdesc.get_proc_name pdesc in + Domain.blocking_call ~caller ~callee loc astate + else if is_on_main_thread callee then Domain.set_on_main_thread astate else - Summary.read_summary pdesc callee_pname - |> Option.value_map ~default:astate - ~f:(Domain.integrate_summary astate callee_pname loc) ) + Summary.read_summary pdesc callee + |> Option.value_map ~default:astate ~f:(Domain.integrate_summary astate callee loc) ) | _ -> astate @@ -212,7 +213,7 @@ let report_direct_blocks_on_main_thread proc_desc summary = let caller_loc = Procdesc.get_loc proc_desc in let caller_pname = Procdesc.get_proc_name proc_desc in let error_message = - Format.asprintf "May block while on main thread. Eventually: %a" LockEvent.pp_event + Format.asprintf "UI-thread method may block; %a" LockEvent.pp_event eventually.LockEvent.event in let exn = diff --git a/infer/src/concurrency/starvationDomain.ml b/infer/src/concurrency/starvationDomain.ml index fa9c7564e..a20a75ab9 100644 --- a/infer/src/concurrency/starvationDomain.ml +++ b/infer/src/concurrency/starvationDomain.ml @@ -105,8 +105,8 @@ module LockEvent = struct let make_blocks msg loc = {event= MayBlock msg; loc; trace= []} - let make_blocking_call pname loc = - let descr = F.asprintf "Calls %a" Typ.Procname.pp pname in + let make_blocking_call ~caller ~callee loc = + let descr = F.asprintf "calls %a from %a" Typ.Procname.pp callee Typ.Procname.pp caller in make_blocks descr loc @@ -131,9 +131,9 @@ module LockOrder = struct let pp fmt o = match o.first with | None -> - F.fprintf fmt "Eventually %a" LockEvent.pp o.eventually + F.fprintf fmt "eventually %a" LockEvent.pp o.eventually | Some lock -> - F.fprintf fmt "First %a and before releasing it %a" LockEvent.pp lock LockEvent.pp + F.fprintf fmt "first %a, and before releasing it, %a" LockEvent.pp lock LockEvent.pp o.eventually @@ -248,8 +248,8 @@ let acquire ((ls, lo), main) loc lockid = ((ls', lo'), main) -let blocking_call pname loc ((ls, lo), main) = - let newlock_event = LockEvent.make_blocking_call pname loc in +let blocking_call ~caller ~callee loc ((ls, lo), main) = + let newlock_event = LockEvent.make_blocking_call ~caller ~callee loc in let lo' = add_order_pairs ls newlock_event lo in ((ls, lo'), main) diff --git a/infer/src/concurrency/starvationDomain.mli b/infer/src/concurrency/starvationDomain.mli index 04e69d996..b77d6dcff 100644 --- a/infer/src/concurrency/starvationDomain.mli +++ b/infer/src/concurrency/starvationDomain.mli @@ -62,7 +62,8 @@ val acquire : astate -> Location.t -> LockIdentity.t -> astate val release : astate -> LockIdentity.t -> astate -val blocking_call : Typ.Procname.t -> Location.t -> astate -> astate +val blocking_call : + caller:Typ.Procname.t -> callee:Typ.Procname.t -> Location.t -> astate -> astate val set_on_main_thread : astate -> astate diff --git a/infer/tests/codetoanalyze/java/starvation/issues.exp b/infer/tests/codetoanalyze/java/starvation/issues.exp index 6bac46d7f..86174ea10 100644 --- a/infer/tests/codetoanalyze/java/starvation/issues.exp +++ b/infer/tests/codetoanalyze/java/starvation/issues.exp @@ -1,13 +1,13 @@ -codetoanalyze/java/starvation/Binders.java, void Binders.annotationBad(), 0, STARVATION, ERROR, [Method start: void Binders.annotationBad(),Method call: void Binders.doTransact(),Calls boolean Binder.transact(int,Parcel,Parcel,int)] -codetoanalyze/java/starvation/Binders.java, void Binders.interBad(), 0, STARVATION, ERROR, [Method start: void Binders.interBad(),Calls boolean Binder.transact(int,Parcel,Parcel,int)] -codetoanalyze/java/starvation/Binders.java, void Binders.intraBad(), 0, STARVATION, ERROR, [Method start: void Binders.intraBad(),Method call: void Binders.doTransact(),Calls boolean Binder.transact(int,Parcel,Parcel,int)] -codetoanalyze/java/starvation/Countdwn.java, void Countdwn.awaitOnMainByAnnotBad(), 0, STARVATION, ERROR, [Method start: void Countdwn.awaitOnMainByAnnotBad(),Calls void CountDownLatch.await()] -codetoanalyze/java/starvation/Countdwn.java, void Countdwn.awaitOnMainByCallBad(), 0, STARVATION, ERROR, [Method start: void Countdwn.awaitOnMainByCallBad(),Calls void CountDownLatch.await()] +codetoanalyze/java/starvation/Binders.java, void Binders.annotationBad(), 0, STARVATION, ERROR, [Method start: void Binders.annotationBad(),Method call: void Binders.doTransact(),calls boolean Binder.transact(int,Parcel,Parcel,int) from void Binders.doTransact()] +codetoanalyze/java/starvation/Binders.java, void Binders.interBad(), 0, STARVATION, ERROR, [Method start: void Binders.interBad(),calls boolean Binder.transact(int,Parcel,Parcel,int) from void Binders.interBad()] +codetoanalyze/java/starvation/Binders.java, void Binders.intraBad(), 0, STARVATION, ERROR, [Method start: void Binders.intraBad(),Method call: void Binders.doTransact(),calls boolean Binder.transact(int,Parcel,Parcel,int) from void Binders.doTransact()] +codetoanalyze/java/starvation/Countdwn.java, void Countdwn.awaitOnMainByAnnotBad(), 0, STARVATION, ERROR, [Method start: void Countdwn.awaitOnMainByAnnotBad(),calls void CountDownLatch.await() from void Countdwn.awaitOnMainByAnnotBad()] +codetoanalyze/java/starvation/Countdwn.java, void Countdwn.awaitOnMainByCallBad(), 0, STARVATION, ERROR, [Method start: void Countdwn.awaitOnMainByCallBad(),calls void CountDownLatch.await() from void Countdwn.awaitOnMainByCallBad()] codetoanalyze/java/starvation/InnerClass.java, void InnerClass$InnerClassA.innerOuterBad(), 0, STARVATION, ERROR, [[Trace 1] Locks this in class InnerClass$InnerClassA*,Method call: void InnerClass.bar(),Locks this in class InnerClass*,[Trace 2] Locks this in class InnerClass*,Method call: void InnerClass$InnerClassA.baz(),Locks this in class InnerClass$InnerClassA*] codetoanalyze/java/starvation/InnerClass.java, void InnerClass.outerInnerBad(InnerClass$InnerClassA), 0, STARVATION, ERROR, [[Trace 1] Locks this in class InnerClass*,Method call: void InnerClass$InnerClassA.baz(),Locks this in class InnerClass$InnerClassA*,[Trace 2] Method start: InnerClass$InnerClassA.(InnerClass,Object),Locks this in class InnerClass$InnerClassA*,Method call: void InnerClass.bar(),Locks this in class InnerClass*] codetoanalyze/java/starvation/Interclass.java, void InterclassA.interclass2Bad(Interclass), 0, STARVATION, ERROR, [[Trace 1] Locks this in class InterclassA*,Method call: void Interclass.interclass2Bad(),Locks this in class Interclass*,[Trace 2] Locks this in class Interclass*,Method call: void InterclassA.interclass1Bad(),Locks this in class InterclassA*] codetoanalyze/java/starvation/Interproc.java, void Interproc.interproc1Bad(InterprocA), 0, STARVATION, ERROR, [[Trace 1] Locks this in class Interproc*,Method call: void Interproc.interproc2Bad(InterprocA),Locks b in class InterprocA*,[Trace 2] Locks this in class InterprocA*,Method call: void InterprocA.interproc2Bad(Interproc),Locks d in class Interproc*] codetoanalyze/java/starvation/Intraproc.java, void IntraprocA.intraBad(Intraproc), 0, STARVATION, ERROR, [[Trace 1] Method start: void IntraprocA.intraBad(Intraproc),Locks this in class IntraprocA*,Locks o in class Intraproc*,[Trace 2] Method start: void Intraproc.intraBad(IntraprocA),Locks this in class Intraproc*,Locks o in class IntraprocA*] -codetoanalyze/java/starvation/JavaIO.java, void JavaIO.fileReadBad(), 0, STARVATION, ERROR, [Method start: void JavaIO.fileReadBad(),Method call: int JavaIO.doFileRead(),Calls int InputStreamReader.read()] -codetoanalyze/java/starvation/JavaIO.java, void JavaIO.streamReadBad(), 0, STARVATION, ERROR, [Method start: void JavaIO.streamReadBad(),Method call: String JavaIO.doStreamRead(),Calls String DataInputStream.readUTF()] +codetoanalyze/java/starvation/JavaIO.java, void JavaIO.fileReadBad(), 0, STARVATION, ERROR, [Method start: void JavaIO.fileReadBad(),Method call: int JavaIO.doFileRead(),calls int InputStreamReader.read() from int JavaIO.doFileRead()] +codetoanalyze/java/starvation/JavaIO.java, void JavaIO.streamReadBad(), 0, STARVATION, ERROR, [Method start: void JavaIO.streamReadBad(),Method call: String JavaIO.doStreamRead(),calls String DataInputStream.readUTF() from String JavaIO.doStreamRead()] codetoanalyze/java/starvation/StaticLock.java, void StaticLock.lockOtherClassOneWayBad(), 0, STARVATION, ERROR, [[Trace 1] Method start: void StaticLock.lockOtherClassOneWayBad(),Locks StaticLock$0 in class java.lang.Class*,Locks this in class StaticLock*,[Trace 2] Locks this in class StaticLock*,Method call: void StaticLock.staticSynced(),Locks StaticLock$0 in class java.lang.Class*]