From ca1ba2511b448f231b6c4b707b6402d2dec225a4 Mon Sep 17 00:00:00 2001 From: Nikos Gorogiannis Date: Thu, 9 Jan 2020 02:57:08 -0800 Subject: [PATCH] [starvation] tests for a multi-file C++ deadlock Summary: Demonstrate that the per-file type environments don't prevent the deadlock report here. The fear was that when the analyser tries to locate the methods of the endpoint class, it might fail to do so because the types might be stored in different type environments (per file). Reviewed By: mityal Differential Revision: D19225908 fbshipit-source-id: 097e4aeea --- .../cpp/starvation/crossfile-1.cpp | 20 +++++++++++ .../cpp/starvation/crossfile-1.h | 33 +++++++++++++++++++ .../cpp/starvation/crossfile-2.cpp | 20 +++++++++++ .../cpp/starvation/crossfile-2.h | 31 +++++++++++++++++ .../codetoanalyze/cpp/starvation/issues.exp | 2 ++ 5 files changed, 106 insertions(+) create mode 100644 infer/tests/codetoanalyze/cpp/starvation/crossfile-1.cpp create mode 100644 infer/tests/codetoanalyze/cpp/starvation/crossfile-1.h create mode 100644 infer/tests/codetoanalyze/cpp/starvation/crossfile-2.cpp create mode 100644 infer/tests/codetoanalyze/cpp/starvation/crossfile-2.h diff --git a/infer/tests/codetoanalyze/cpp/starvation/crossfile-1.cpp b/infer/tests/codetoanalyze/cpp/starvation/crossfile-1.cpp new file mode 100644 index 000000000..10ca63572 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/starvation/crossfile-1.cpp @@ -0,0 +1,20 @@ +/* + * 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. + */ + +#include "crossfile-1.h" + +// a deadlock should be reported here +void CrossFileOne::lock_my_mutex_first_then_the_other() { + _mutex.lock(); + _other->just_lock_my_mutex(); + _mutex.unlock(); +} + +void CrossFileOne::just_lock_my_mutex() { + _mutex.lock(); + _mutex.unlock(); +} diff --git a/infer/tests/codetoanalyze/cpp/starvation/crossfile-1.h b/infer/tests/codetoanalyze/cpp/starvation/crossfile-1.h new file mode 100644 index 000000000..e1b6462c9 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/starvation/crossfile-1.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef CROSS_FILE_ONE +#define CROSS_FILE_ONE + +/* The goal of this test is to demonstrate that the per-file type +environments don't prevent the deadlock report here */ + +// unused include to distinguish the two per-file type environments +#include +#include + +class CrossFileOne; + +#include "crossfile-2.h" + +class CrossFileOne { + public: + CrossFileOne() {} + void lock_my_mutex_first_then_the_other(); + void just_lock_my_mutex(); + + private: + std::mutex _mutex; + CrossFileTwo* _other; +}; + +#endif diff --git a/infer/tests/codetoanalyze/cpp/starvation/crossfile-2.cpp b/infer/tests/codetoanalyze/cpp/starvation/crossfile-2.cpp new file mode 100644 index 000000000..c4ac8e7d0 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/starvation/crossfile-2.cpp @@ -0,0 +1,20 @@ +/* + * 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. + */ + +#include "crossfile-2.h" + +// a deadlock should be reported here +void CrossFileTwo::lock_my_mutex_first_then_the_other() { + _mutex.lock(); + _other->just_lock_my_mutex(); + _mutex.unlock(); +} + +void CrossFileTwo::just_lock_my_mutex() { + _mutex.lock(); + _mutex.unlock(); +} diff --git a/infer/tests/codetoanalyze/cpp/starvation/crossfile-2.h b/infer/tests/codetoanalyze/cpp/starvation/crossfile-2.h new file mode 100644 index 000000000..d317bb708 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/starvation/crossfile-2.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/* The goal of this test is to demonstrate that the per-file type +environments don't prevent the deadlock report here */ + +#ifndef CROSS_FILE_TWO +#define CROSS_FILE_TWO + +#include + +class CrossFileTwo; + +#include "crossfile-1.h" + +class CrossFileTwo { + public: + CrossFileTwo() {} + void lock_my_mutex_first_then_the_other(); + void just_lock_my_mutex(); + + private: + std::mutex _mutex; + CrossFileOne* _other; +}; + +#endif diff --git a/infer/tests/codetoanalyze/cpp/starvation/issues.exp b/infer/tests/codetoanalyze/cpp/starvation/issues.exp index bca150e38..ee15ad545 100644 --- a/infer/tests/codetoanalyze/cpp/starvation/issues.exp +++ b/infer/tests/codetoanalyze/cpp/starvation/issues.exp @@ -6,6 +6,8 @@ codetoanalyze/cpp/starvation/basics.cpp, basics::SelfDeadlock::interproc1_bad, 1 codetoanalyze/cpp/starvation/basics.cpp, basics::SelfDeadlock::thread_bad, 105, DEADLOCK, no_bucket, ERROR, [In method `basics::SelfDeadlock::thread_bad`, locks `this.mutex_` in `class basics::SelfDeadlock`, locks `this.mutex_` in `class basics::SelfDeadlock`] codetoanalyze/cpp/starvation/basics.cpp, basics::WithGuard::thread1_bad, 44, DEADLOCK, no_bucket, ERROR, [[Trace 1] `basics::WithGuard::thread1_bad`, locks `this.mutex_1` in `class basics::WithGuard`, locks `this.mutex_2` in `class basics::WithGuard`,[Trace 2] `basics::WithGuard::thread2_bad`, locks `this.mutex_2` in `class basics::WithGuard`, locks `this.mutex_1` in `class basics::WithGuard`] codetoanalyze/cpp/starvation/basics.cpp, basics::WithGuard::thread2_bad, 49, DEADLOCK, no_bucket, ERROR, [[Trace 1] `basics::WithGuard::thread2_bad`, locks `this.mutex_2` in `class basics::WithGuard`, locks `this.mutex_1` in `class basics::WithGuard`,[Trace 2] `basics::WithGuard::thread1_bad`, locks `this.mutex_1` in `class basics::WithGuard`, locks `this.mutex_2` in `class basics::WithGuard`] +codetoanalyze/cpp/starvation/crossfile-1.cpp, CrossFileOne::lock_my_mutex_first_then_the_other, 12, DEADLOCK, no_bucket, ERROR, [[Trace 1] `CrossFileOne::lock_my_mutex_first_then_the_other`, locks `this._mutex` in `class CrossFileOne`,Method call: `CrossFileTwo::just_lock_my_mutex`, locks `this._mutex` in `class CrossFileTwo`,[Trace 2] `CrossFileTwo::lock_my_mutex_first_then_the_other`, locks `this._mutex` in `class CrossFileTwo`,Method call: `CrossFileOne::just_lock_my_mutex`, locks `this._mutex` in `class CrossFileOne`] +codetoanalyze/cpp/starvation/crossfile-2.cpp, CrossFileTwo::lock_my_mutex_first_then_the_other, 12, DEADLOCK, no_bucket, ERROR, [[Trace 1] `CrossFileTwo::lock_my_mutex_first_then_the_other`, locks `this._mutex` in `class CrossFileTwo`,Method call: `CrossFileOne::just_lock_my_mutex`, locks `this._mutex` in `class CrossFileOne`,[Trace 2] `CrossFileOne::lock_my_mutex_first_then_the_other`, locks `this._mutex` in `class CrossFileOne`,Method call: `CrossFileTwo::just_lock_my_mutex`, locks `this._mutex` in `class CrossFileTwo`] codetoanalyze/cpp/starvation/skip.cpp, skipped::Skip::not_skipped_bad, 19, DEADLOCK, no_bucket, ERROR, [In method `skipped::Skip::not_skipped_bad`,Method call: `skipped::Skip::private_deadlock`, locks `this.mutex_` in `class skipped::Skip`, locks `this.mutex_` in `class skipped::Skip`] codetoanalyze/cpp/starvation/skip.cpp, skipped::SkipTemplate::not_skipped_bad, 44, DEADLOCK, no_bucket, ERROR, [In method `skipped::SkipTemplate::not_skipped_bad`,Method call: `skipped::SkipTemplate::private_deadlock`, locks `this.mutex_` in `class skipped::SkipTemplate`, locks `this.mutex_` in `class skipped::SkipTemplate`] codetoanalyze/cpp/starvation/skip.cpp, skipped::UseTemplate::foo, 53, DEADLOCK, no_bucket, ERROR, [In method `skipped::UseTemplate::foo`,Method call: `skipped::SkipTemplate::not_skipped_bad`,Method call: `skipped::SkipTemplate::private_deadlock`, locks `this.mutex_` in `class skipped::SkipTemplate`, locks `this.mutex_` in `class skipped::SkipTemplate`]