android_system_core/libappfuse/include/libappfuse/FuseBridgeLoop.h
hyeeun.jun@samsung.com 612fc47090 Fix Deadlock Issue On AppFuseBridge
There are two locks used by AppFuseBridge.
First is it's object lock, and the second is a mutex lock in app fuse library.
There are two oppsite routines to get those locks.

  (Thread A) Got Java lock -> Try to get Native lock
  (Thread B)        Got Native lock -> Try to get Java lock

The order must be followed to obtain two locks.
If not, the dead lock will be caused.
Therefore we change the routine to get the mutex lock first, and the object lock later.

Signed-off-by: hyeeun.jun@samsung.com <hyeeun.jun@samsung.com>
Bug: https://issuetracker.google.com/issues/145707568
Bug: 157535024
Test: atest --test-mapping apex/blobstore

Change-Id: I0ab002da9a0b7ca2f518d50ab477a080cabe3788
2020-06-17 13:39:21 +01:00

77 lines
2 KiB
C++

/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specic language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_LIBAPPFUSE_FUSEBRIDGELOOP_H_
#define ANDROID_LIBAPPFUSE_FUSEBRIDGELOOP_H_
#include <map>
#include <mutex>
#include <queue>
#include <unordered_set>
#include <android-base/macros.h>
#include "libappfuse/FuseBuffer.h"
namespace android {
namespace fuse {
class FuseBridgeLoopCallback {
public:
virtual void OnMount(int mount_id) = 0;
virtual void OnClosed(int mount_id) = 0;
virtual ~FuseBridgeLoopCallback() = default;
};
class FuseBridgeEntry;
class BridgeEpollController;
class FuseBridgeLoop final {
public:
FuseBridgeLoop();
~FuseBridgeLoop();
void Start(FuseBridgeLoopCallback* callback);
// Add bridge to the loop. It's OK to invoke the method from a different
// thread from one which invokes |Start|.
bool AddBridge(int mount_id, base::unique_fd dev_fd, base::unique_fd proxy_fd);
static void Lock();
static void Unlock();
private:
bool ProcessEventLocked(const std::unordered_set<FuseBridgeEntry*>& entries,
FuseBridgeLoopCallback* callback);
std::unique_ptr<BridgeEpollController> epoll_controller_;
// Map between |mount_id| and bridge entry.
std::map<int, std::unique_ptr<FuseBridgeEntry>> bridges_;
// Lock for multi-threading.
static std::recursive_mutex mutex_;
bool opened_;
DISALLOW_COPY_AND_ASSIGN(FuseBridgeLoop);
};
} // namespace fuse
} // namespace android
#endif // ANDROID_LIBAPPFUSE_FUSEBRIDGELOOP_H_