diff --git a/infer/src/concurrency/starvation.ml b/infer/src/concurrency/starvation.ml index e63e56c2c..57c143dab 100644 --- a/infer/src/concurrency/starvation.ml +++ b/infer/src/concurrency/starvation.ml @@ -168,7 +168,7 @@ let log_issue current_pname current_loc ltr exn = inner class but this is no longer obvious in the path, because of nested-class path normalisation. The net effect of the above issues is that we will only see these locks in conflicting pairs once, as opposed to twice with all other deadlock pairs. *) -let report_deadlocks get_proc_desc tenv current_pdesc (summary, _) = +let report_deadlocks get_proc_desc tenv current_pdesc (summary, current_main) = let open StarvationDomain in let current_loc = Procdesc.get_loc current_pdesc in let current_pname = Procdesc.get_proc_name current_pdesc in @@ -208,7 +208,8 @@ let report_deadlocks get_proc_desc tenv current_pdesc (summary, _) = get_summaries_of_methods_in_class get_proc_desc tenv current_pdesc endpoint_class in (* for each summary related to the endpoint, analyse and report on its pairs *) - List.iter endpoint_summaries ~f:(fun (endpoint_pdesc, (summary, _)) -> + List.iter endpoint_summaries ~f:(fun (endpoint_pdesc, (summary, endpoint_main)) -> + if not (current_main && endpoint_main) then let endpoint_loc = Procdesc.get_loc endpoint_pdesc in let endpoint_pname = Procdesc.get_proc_name endpoint_pdesc in LockOrderDomain.iter (report_endpoint_elem elem endpoint_pname endpoint_loc) summary diff --git a/infer/tests/codetoanalyze/java/starvation/UIDeadlock.java b/infer/tests/codetoanalyze/java/starvation/UIDeadlock.java new file mode 100644 index 000000000..520c3f1ea --- /dev/null +++ b/infer/tests/codetoanalyze/java/starvation/UIDeadlock.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +import android.support.annotation.UiThread; + +class UIDeadlock { + Object lockA, lockB; + + @UiThread + public synchronized void onUIThreadAOk() { + synchronized(lockA) {} + } + + @UiThread + public void onUIThreadBOk() { + synchronized(lockA) { + synchronized(this) {} + } + } + + @UiThread + public synchronized void onUIThreadBad() { + synchronized(lockB) {} + } + + public void notOnUIThreadBad() { + synchronized(lockB) { + synchronized(this) {} + } + } +} diff --git a/infer/tests/codetoanalyze/java/starvation/issues.exp b/infer/tests/codetoanalyze/java/starvation/issues.exp index 62acb039a..1ac4585ef 100644 --- a/infer/tests/codetoanalyze/java/starvation/issues.exp +++ b/infer/tests/codetoanalyze/java/starvation/issues.exp @@ -22,4 +22,6 @@ codetoanalyze/java/starvation/Intraproc.java, void IntraprocA.intraBad(Intraproc codetoanalyze/java/starvation/JavaIO.java, void JavaIO.fileReadBad(), 32, STARVATION, ERROR, [ void JavaIO.fileReadBad(),Method call: int JavaIO.doFileRead(),calls int InputStreamReader.read() from int JavaIO.doFileRead()] codetoanalyze/java/starvation/JavaIO.java, void JavaIO.streamReadBad(), 37, STARVATION, ERROR, [ void JavaIO.streamReadBad(),Method call: String JavaIO.doStreamRead(),calls String DataInputStream.readUTF() from String JavaIO.doStreamRead()] codetoanalyze/java/starvation/StaticLock.java, void StaticLock.lockOtherClassOneWayBad(), 24, STARVATION, ERROR, [[Trace 1] void StaticLock.lockOtherClassOneWayBad(),locks `StaticLock$0` in class `java.lang.Class*`,locks `this` in class `StaticLock*`,[Trace 2] void StaticLock.lockOtherClassAnotherWayNad(),locks `this` in class `StaticLock*`,Method call: void StaticLock.staticSynced(),locks `StaticLock$0` in class `java.lang.Class*`] +codetoanalyze/java/starvation/UIDeadlock.java, void UIDeadlock.notOnUIThreadBad(), 32, STARVATION, ERROR, [[Trace 1] void UIDeadlock.notOnUIThreadBad(),locks `this.UIDeadlock.lockB` in class `UIDeadlock*`,locks `this` in class `UIDeadlock*`,[Trace 2] void UIDeadlock.onUIThreadBad(),locks `this` in class `UIDeadlock*`,locks `this.UIDeadlock.lockB` in class `UIDeadlock*`] +codetoanalyze/java/starvation/UIDeadlock.java, void UIDeadlock.onUIThreadBad(), 28, STARVATION, ERROR, [[Trace 1] void UIDeadlock.onUIThreadBad(),locks `this` in class `UIDeadlock*`,locks `this.UIDeadlock.lockB` in class `UIDeadlock*`,[Trace 2] void UIDeadlock.notOnUIThreadBad(),locks `this.UIDeadlock.lockB` in class `UIDeadlock*`,locks `this` in class `UIDeadlock*`] codetoanalyze/java/starvation/VisDispFrame.java, void VisDispFrame.callsGetVisibleDisplayFrameOnUiThreadBad(), 19, STARVATION, ERROR, [ void VisDispFrame.callsGetVisibleDisplayFrameOnUiThreadBad(),calls void View.getWindowVisibleDisplayFrame(Rect) from void VisDispFrame.callsGetVisibleDisplayFrameOnUiThreadBad()]