diff --git a/infer/src/concurrency/RacerDConfig.ml b/infer/src/concurrency/RacerDConfig.ml index 5709112f7..6b8a3906e 100644 --- a/infer/src/concurrency/RacerDConfig.ml +++ b/infer/src/concurrency/RacerDConfig.ml @@ -603,6 +603,11 @@ module Models = struct is_call_of_class_or_superclass ["android.accounts.AccountManager"] "setUserData" + let is_asyncTask_get_without_timeout = + let actuals_pred actuals = Int.equal 1 (List.length actuals) in + is_call_of_class_or_superclass ~actuals_pred ["android.os.AsyncTask"] "get" + + let may_block = let matchers = [ is_blocking_java_io @@ -610,7 +615,8 @@ module Models = struct ; is_two_way_binder_transact ; is_getWindowVisibleDisplayFrame ; is_future_get - ; is_accountManager_setUserData ] + ; is_accountManager_setUserData + ; is_asyncTask_get_without_timeout ] in fun tenv pn actuals -> List.exists matchers ~f:(fun matcher -> matcher tenv pn actuals) end diff --git a/infer/tests/codetoanalyze/java/starvation/AsyncTaskGet.java b/infer/tests/codetoanalyze/java/starvation/AsyncTaskGet.java new file mode 100644 index 000000000..aca27677e --- /dev/null +++ b/infer/tests/codetoanalyze/java/starvation/AsyncTaskGet.java @@ -0,0 +1,56 @@ +/* + * 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 java.util.concurrent.TimeUnit; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import android.support.annotation.UiThread; +import android.os.AsyncTask; + +class AsyncTaskGet { + CountTask task; + Object lock; + + @UiThread + void taskGetOnUiThreadBad() throws InterruptedException, ExecutionException { + task.get(); + } + + @UiThread + void taskGetWithTimeoutOnUiThreadOk() + throws TimeoutException, InterruptedException, ExecutionException { + task.get(1000, TimeUnit.NANOSECONDS); + } + + @UiThread + void lockOnUiThreadBad() { + synchronized(lock) {} + } + + void taskGetUnderLock() throws InterruptedException, ExecutionException { + synchronized(lock) { + task.get(); + } + } + + void taskGetonBGThreadOk() throws InterruptedException, ExecutionException { + task.get(); + } +} + +class CountTask extends AsyncTask { + protected Long doInBackground(Integer... ints) { + long totalSize = 0; + for (int i = 0; i < ints.length; i++) { + totalSize += ints[i]; + if (isCancelled()) break; + } + return totalSize; + } + } diff --git a/infer/tests/codetoanalyze/java/starvation/issues.exp b/infer/tests/codetoanalyze/java/starvation/issues.exp index 518cd9e6b..9218d3876 100644 --- a/infer/tests/codetoanalyze/java/starvation/issues.exp +++ b/infer/tests/codetoanalyze/java/starvation/issues.exp @@ -1,5 +1,7 @@ codetoanalyze/java/starvation/AccMgr.java, void AccMgr.lockOnUiThreadBad(), 26, STARVATION, ERROR, [[Trace 1] void AccMgr.lockOnUiThreadBad(),locks `this.AccMgr.lock` in class `AccMgr*`,[Trace 2] void AccMgr.setUserDataUnderLock(),locks `this.AccMgr.lock` in class `AccMgr*`,calls void AccountManager.setUserData(Account,String,String) from void AccMgr.setUserDataUnderLock()] codetoanalyze/java/starvation/AccMgr.java, void AccMgr.onUiThreadBad(), 21, STARVATION, ERROR, [ void AccMgr.onUiThreadBad(),calls void AccountManager.setUserData(Account,String,String) from void AccMgr.onUiThreadBad()] +codetoanalyze/java/starvation/AsyncTaskGet.java, void AsyncTaskGet.lockOnUiThreadBad(), 32, STARVATION, ERROR, [[Trace 1] void AsyncTaskGet.lockOnUiThreadBad(),locks `this.AsyncTaskGet.lock` in class `AsyncTaskGet*`,[Trace 2] void AsyncTaskGet.taskGetUnderLock(),locks `this.AsyncTaskGet.lock` in class `AsyncTaskGet*`,calls Object AsyncTask.get() from void AsyncTaskGet.taskGetUnderLock()] +codetoanalyze/java/starvation/AsyncTaskGet.java, void AsyncTaskGet.taskGetOnUiThreadBad(), 21, STARVATION, ERROR, [ void AsyncTaskGet.taskGetOnUiThreadBad(),calls Object AsyncTask.get() from void AsyncTaskGet.taskGetOnUiThreadBad()] codetoanalyze/java/starvation/Binders.java, void Binders.annotationBad(), 36, STARVATION, ERROR, [ 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(), 25, STARVATION, ERROR, [ void Binders.interBad(),calls boolean Binder.transact(int,Parcel,Parcel,int) from void Binders.interBad()] codetoanalyze/java/starvation/Binders.java, void Binders.intraBad(), 30, STARVATION, ERROR, [ void Binders.intraBad(),Method call: void Binders.doTransact(),calls boolean Binder.transact(int,Parcel,Parcel,int) from void Binders.doTransact()]