vehicle-aidl: Fix various race condition

mThread should not be created in initization list,
since class member variables are not ready yet,
and the thread will access those variables.

Even if the shared variable is atomic, it must be modified under the
mutex in order to correctly publish the modification to the waiting
thread.

Bug: 231668271
Test: android.hardware.automotive.vehicle@V1-default-service_fuzzer
Change-Id: Ibbf36ddf9edcaa8d016349631784f54f6fd6c877
This commit is contained in:
Keith Mok
2022-05-06 07:39:04 +00:00
parent 85aebe3ee2
commit 22ebbf7822
4 changed files with 40 additions and 20 deletions

View File

@@ -28,11 +28,18 @@ namespace V2_0 {
namespace impl {
GeneratorHub::GeneratorHub(const OnHalEvent& onHalEvent)
: mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
GeneratorHub::GeneratorHub(const OnHalEvent& onHalEvent) : mOnHalEvent(onHalEvent) {
mThread = std::thread(&GeneratorHub::run, this);
}
GeneratorHub::~GeneratorHub() {
mShuttingDownFlag.store(true);
{
// Even if the shared variable is atomic, it must be modified under the
// mutex in order to correctly publish the modification to the waiting
// thread.
std::unique_lock<std::mutex> g(mLock);
mShuttingDownFlag.store(true);
}
mCond.notify_all();
if (mThread.joinable()) {
mThread.join();

View File

@@ -29,11 +29,18 @@ namespace fake {
using ::android::base::ScopedLockAssertion;
GeneratorHub::GeneratorHub(OnHalEvent&& onHalEvent)
: mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
GeneratorHub::GeneratorHub(OnHalEvent&& onHalEvent) : mOnHalEvent(onHalEvent) {
mThread = std::thread(&GeneratorHub::run, this);
}
GeneratorHub::~GeneratorHub() {
mShuttingDownFlag.store(true);
{
// Even if the shared variable is atomic, it must be modified under the
// mutex in order to correctly publish the modification to the waiting
// thread.
std::unique_lock<std::mutex> lock(mGeneratorsLock);
mShuttingDownFlag.store(true);
}
mCond.notify_all();
if (mThread.joinable()) {
mThread.join();

View File

@@ -21,7 +21,6 @@
#include <android-base/result.h>
#include <android-base/thread_annotations.h>
#include <atomic>
#include <list>
#include <mutex>
#include <thread>
@@ -85,7 +84,7 @@ class PendingRequestPool final {
std::unordered_map<const void*, std::list<PendingRequest>> mPendingRequestsByClient
GUARDED_BY(mLock);
std::thread mThread;
std::atomic<bool> mThreadStop = false;
bool mThreadStop = false;
std::condition_variable mCv;
std::mutex mCvLock;

View File

@@ -39,20 +39,27 @@ constexpr int64_t CHECK_TIME_IN_NANO = 1'000'000'000;
} // namespace
PendingRequestPool::PendingRequestPool(int64_t timeoutInNano)
: mTimeoutInNano(timeoutInNano), mThread([this] {
// [this] must be alive within this thread because destructor would wait for this thread
// to exit.
int64_t sleepTime = std::min(mTimeoutInNano, static_cast<int64_t>(CHECK_TIME_IN_NANO));
std::unique_lock<std::mutex> lk(mCvLock);
while (!mCv.wait_for(lk, std::chrono::nanoseconds(sleepTime),
[this] { return mThreadStop.load(); })) {
checkTimeout();
}
}) {}
PendingRequestPool::PendingRequestPool(int64_t timeoutInNano) : mTimeoutInNano(timeoutInNano) {
mThread = std::thread([this] {
// [this] must be alive within this thread because destructor would wait for this thread
// to exit.
int64_t sleepTime = std::min(mTimeoutInNano, static_cast<int64_t>(CHECK_TIME_IN_NANO));
std::unique_lock<std::mutex> lk(mCvLock);
while (!mCv.wait_for(lk, std::chrono::nanoseconds(sleepTime),
[this] { return mThreadStop; })) {
checkTimeout();
}
});
}
PendingRequestPool::~PendingRequestPool() {
mThreadStop = true;
{
// Even if the shared variable is atomic, it must be modified under the
// mutex in order to correctly publish the modification to the waiting
// thread.
std::unique_lock<std::mutex> lk(mCvLock);
mThreadStop = true;
}
mCv.notify_all();
if (mThread.joinable()) {
mThread.join();