[starvation] whitelist @WorkerThread methods

Reviewed By: mbouaziz, ddino

Differential Revision: D9480061

fbshipit-source-id: 4648319e1
master
Nikos Gorogiannis 6 years ago committed by Facebook Github Bot
parent a06685c517
commit 14556f52b4

@ -107,6 +107,8 @@ let visibleForTesting = "VisibleForTesting"
let volatile = "volatile" let volatile = "volatile"
let worker_thread = "WorkerThread"
let ia_has_annotation_with (ia: Annot.Item.t) (predicate: Annot.t -> bool) : bool = let ia_has_annotation_with (ia: Annot.Item.t) (predicate: Annot.t -> bool) : bool =
List.exists ~f:(fun (a, _) -> predicate a) ia List.exists ~f:(fun (a, _) -> predicate a) ia
@ -242,3 +244,5 @@ let ia_is_on_unmount ia = ia_ends_with ia on_unmount
let ia_is_ui_thread ia = ia_ends_with ia ui_thread let ia_is_ui_thread ia = ia_ends_with ia ui_thread
let ia_is_thread_confined ia = ia_ends_with ia thread_confined let ia_is_thread_confined ia = ia_ends_with ia thread_confined
let ia_is_worker_thread ia = ia_ends_with ia worker_thread

@ -120,6 +120,8 @@ val ia_is_ui_thread : Annot.Item.t -> bool
val ia_is_volatile : Annot.Item.t -> bool val ia_is_volatile : Annot.Item.t -> bool
val ia_is_worker_thread : Annot.Item.t -> bool
val pdesc_get_return_annot : Procdesc.t -> Annot.Item.t val pdesc_get_return_annot : Procdesc.t -> Annot.Item.t
(** get the list of annotations on the return value of [pdesc] *) (** get the list of annotations on the return value of [pdesc] *)

@ -512,7 +512,14 @@ module Models = struct
|| Annotations.ia_is_on_unbind annot || Annotations.ia_is_on_unmount annot || Annotations.ia_is_on_unbind annot || Annotations.ia_is_on_unmount annot
in in
let pname = Procdesc.get_proc_name proc_desc in let pname = Procdesc.get_proc_name proc_desc in
if Annotations.pdesc_has_return_annot proc_desc is_annot then if
Annotations.pdesc_has_return_annot proc_desc Annotations.ia_is_worker_thread
|| find_annotated_or_overriden_annotated_method Annotations.ia_is_worker_thread pname tenv
|> Option.is_some
|| get_current_class_and_annotated_superclasses Annotations.ia_is_worker_thread tenv pname
|> Option.value_map ~default:false ~f:(function _, [] -> false | _ -> true)
then None
else if Annotations.pdesc_has_return_annot proc_desc is_annot then
Some Some
(F.asprintf "%a is annotated %s" (F.asprintf "%a is annotated %s"
(MF.wrap_monospaced Typ.Procname.pp) (MF.wrap_monospaced Typ.Procname.pp)

@ -0,0 +1,37 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import android.os.Binder;
import android.os.RemoteException;
import android.support.annotation.UiThread;
import android.support.annotation.WorkerThread;
class Workers {
Binder b;
void doTransact() throws RemoteException {
b.transact(0, null, null, 0);
}
@WorkerThread
void workerOk() throws RemoteException {
doTransact();
}
// WorkerThread does not propagate up the call stack
@UiThread
void uiThreadBad() throws RemoteException {
workerOk();
}
// WorkerThread wins
@WorkerThread
@UiThread
void bothOk() throws RemoteException {
workerOk();
}
}

@ -41,3 +41,4 @@ codetoanalyze/java/starvation/SuppLint.java, SuppLint.onUiThreadBad():void, 26,
codetoanalyze/java/starvation/ThreadSleep.java, ThreadSleep.indirectSleepOnUIThreadBad():void, 25, STARVATION, no_bucket, ERROR, [[Trace 1] `void ThreadSleep.indirectSleepOnUIThreadBad()`,locks `this.ThreadSleep.lock` in class `ThreadSleep*`,[Trace 2] `void ThreadSleep.lockAndSleepOnNonUIThread()`,locks `this.ThreadSleep.lock` in class `ThreadSleep*`,Method call: `void ThreadSleep.sleepOnAnyThreadOk()`,calls `void Thread.sleep(long)` from `void ThreadSleep.sleepOnAnyThreadOk()`] codetoanalyze/java/starvation/ThreadSleep.java, ThreadSleep.indirectSleepOnUIThreadBad():void, 25, STARVATION, no_bucket, ERROR, [[Trace 1] `void ThreadSleep.indirectSleepOnUIThreadBad()`,locks `this.ThreadSleep.lock` in class `ThreadSleep*`,[Trace 2] `void ThreadSleep.lockAndSleepOnNonUIThread()`,locks `this.ThreadSleep.lock` in class `ThreadSleep*`,Method call: `void ThreadSleep.sleepOnAnyThreadOk()`,calls `void Thread.sleep(long)` from `void ThreadSleep.sleepOnAnyThreadOk()`]
codetoanalyze/java/starvation/ThreadSleep.java, ThreadSleep.sleepOnUIThreadBad():void, 18, STARVATION, no_bucket, ERROR, [`void ThreadSleep.sleepOnUIThreadBad()`,calls `void Thread.sleep(long)` from `void ThreadSleep.sleepOnUIThreadBad()`] codetoanalyze/java/starvation/ThreadSleep.java, ThreadSleep.sleepOnUIThreadBad():void, 18, STARVATION, no_bucket, ERROR, [`void ThreadSleep.sleepOnUIThreadBad()`,calls `void Thread.sleep(long)` from `void ThreadSleep.sleepOnUIThreadBad()`]
codetoanalyze/java/starvation/UIDeadlock.java, UIDeadlock.onUIThreadBad():void, 26, DEADLOCK, no_bucket, 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/UIDeadlock.java, UIDeadlock.onUIThreadBad():void, 26, DEADLOCK, no_bucket, 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/Workers.java, Workers.uiThreadBad():void, 28, STARVATION, no_bucket, ERROR, [`void Workers.uiThreadBad()`,Method call: `void Workers.workerOk()`,Method call: `void Workers.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)` from `void Workers.doTransact()`]

Loading…
Cancel
Save