Reviewed By: da319 Differential Revision: D9042172 fbshipit-source-id: a7052e061master
parent
5b3bca5562
commit
bbd26769c9
@ -0,0 +1,20 @@
|
||||
# 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.
|
||||
|
||||
TESTS_DIR = ../../..
|
||||
|
||||
ANALYZER = checkers
|
||||
# see explanations in cpp/errors/Makefile for the custom isystem
|
||||
CLANG_OPTIONS = -x c++ -std=c++11 -nostdinc++ -isystem$(ROOT_DIR) -isystem$(CLANG_INCLUDES)/c++/v1/ -c
|
||||
|
||||
INFER_OPTIONS = --starvation-only --debug-exceptions --project-root $(TESTS_DIR)
|
||||
|
||||
INFERPRINT_OPTIONS = --issues-tests
|
||||
|
||||
SOURCES = $(wildcard *.cpp)
|
||||
|
||||
include $(TESTS_DIR)/clang.make
|
||||
|
||||
infer-out/report.json: $(MAKEFILE_LIST)
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace basics {
|
||||
|
||||
class Basic {
|
||||
public:
|
||||
Basic() {}
|
||||
|
||||
void thread1() {
|
||||
mutex_1.lock();
|
||||
mutex_2.lock();
|
||||
|
||||
mutex_2.unlock();
|
||||
mutex_1.unlock();
|
||||
}
|
||||
|
||||
void thread2() {
|
||||
mutex_2.lock();
|
||||
mutex_1.lock();
|
||||
|
||||
mutex_1.unlock();
|
||||
mutex_2.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex_1;
|
||||
std::mutex mutex_2;
|
||||
};
|
||||
|
||||
class WithGuard {
|
||||
public:
|
||||
WithGuard() {}
|
||||
|
||||
void thread1() {
|
||||
std::lock_guard<std::mutex> lock1(mutex_1);
|
||||
std::lock_guard<std::mutex> lock2(mutex_2);
|
||||
}
|
||||
|
||||
void thread2() {
|
||||
std::lock_guard<std::mutex> lock2(mutex_2);
|
||||
std::lock_guard<std::mutex> lock1(mutex_1);
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex_1;
|
||||
std::mutex mutex_2;
|
||||
};
|
||||
|
||||
class StdLock {
|
||||
public:
|
||||
StdLock() {}
|
||||
|
||||
// no reports, std::lock magically avoids deadlocks
|
||||
void thread1() {
|
||||
std::lock<std::mutex>(mutex_1, mutex_2);
|
||||
mutex_1.unlock();
|
||||
mutex_2.unlock();
|
||||
}
|
||||
|
||||
void thread2() {
|
||||
std::lock<std::mutex>(mutex_2, mutex_1);
|
||||
mutex_2.unlock();
|
||||
mutex_1.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex_1;
|
||||
std::mutex mutex_2;
|
||||
};
|
||||
} // namespace basics
|
@ -0,0 +1,2 @@
|
||||
codetoanalyze/cpp/starvation/basics.cpp, basics::Basic_thread1, 17, DEADLOCK, no_bucket, ERROR, [[Trace 1] `basics::Basic_thread1`,locks `this.mutex_1` in class `basics::Basic*`,locks `this.mutex_2` in class `basics::Basic*`,[Trace 2] `basics::Basic_thread2`,locks `this.mutex_2` in class `basics::Basic*`,locks `this.mutex_1` in class `basics::Basic*`]
|
||||
codetoanalyze/cpp/starvation/basics.cpp, basics::WithGuard_thread1, 42, DEADLOCK, no_bucket, ERROR, [[Trace 1] `basics::WithGuard_thread1`,locks `this.mutex_1` in class `basics::WithGuard*`,locks `this.mutex_2` in class `basics::WithGuard*`,[Trace 2] `basics::WithGuard_thread2`,locks `this.mutex_2` in class `basics::WithGuard*`,locks `this.mutex_1` in class `basics::WithGuard*`]
|
Loading…
Reference in new issue