[native bridge] Make sure we always unload the native bridge
libnativebridge may allocate some resources during loading and
intialization and de-allocate them when unloading. This makes sure that
we don't leak anything.
Bug: 18097480
Change-Id: I901f2d3c2ab1efb2875388f99e8c5c111ce82d5a
diff --git a/runtime/native_bridge_art_interface.cc b/runtime/native_bridge_art_interface.cc
index bc191b4..b0d8e87 100644
--- a/runtime/native_bridge_art_interface.cc
+++ b/runtime/native_bridge_art_interface.cc
@@ -107,10 +107,11 @@
GetMethodShorty, GetNativeMethodCount, GetNativeMethods
};
-void LoadNativeBridge(std::string& native_bridge_library_filename) {
- android::LoadNativeBridge(native_bridge_library_filename.c_str(), &native_bridge_art_callbacks_);
+bool LoadNativeBridge(std::string& native_bridge_library_filename) {
VLOG(startup) << "Runtime::Setup native bridge library: "
<< (native_bridge_library_filename.empty() ? "(empty)" : native_bridge_library_filename);
+ return android::LoadNativeBridge(native_bridge_library_filename.c_str(),
+ &native_bridge_art_callbacks_);
}
void PreInitializeNativeBridge(std::string dir) {
diff --git a/runtime/native_bridge_art_interface.h b/runtime/native_bridge_art_interface.h
index 026cd82..090cddb 100644
--- a/runtime/native_bridge_art_interface.h
+++ b/runtime/native_bridge_art_interface.h
@@ -26,7 +26,7 @@
// Mirror libnativebridge interface. Done to have the ART callbacks out of line, and not require
// the system/core header file in other files.
-void LoadNativeBridge(std::string& native_bridge_library_filename);
+bool LoadNativeBridge(std::string& native_bridge_library_filename);
// This is mostly for testing purposes, as in a full system this is called by Zygote code.
void PreInitializeNativeBridge(std::string dir);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c16e9ed..50cdf8e 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -146,11 +146,15 @@
target_sdk_version_(0),
implicit_null_checks_(false),
implicit_so_checks_(false),
- implicit_suspend_checks_(false) {
+ implicit_suspend_checks_(false),
+ is_native_bridge_loaded_(false) {
CheckAsmSupportOffsetsAndSizes();
}
Runtime::~Runtime() {
+ if (is_native_bridge_loaded_) {
+ UnloadNativeBridge();
+ }
if (dump_gc_performance_on_shutdown_) {
// This can't be called from the Heap destructor below because it
// could call RosAlloc::InspectAll() which needs the thread_list
@@ -430,12 +434,11 @@
return false;
}
} else {
- bool have_native_bridge = !native_bridge_library_filename_.empty();
- if (have_native_bridge) {
+ if (is_native_bridge_loaded_) {
PreInitializeNativeBridge(".");
}
- DidForkFromZygote(self->GetJniEnv(), have_native_bridge ? NativeBridgeAction::kInitialize :
- NativeBridgeAction::kUnload, GetInstructionSetString(kRuntimeISA));
+ DidForkFromZygote(self->GetJniEnv(), NativeBridgeAction::kInitialize,
+ GetInstructionSetString(kRuntimeISA));
}
StartDaemonThreads();
@@ -514,14 +517,17 @@
void Runtime::DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa) {
is_zygote_ = false;
- switch (action) {
- case NativeBridgeAction::kUnload:
- UnloadNativeBridge();
- break;
+ if (is_native_bridge_loaded_) {
+ switch (action) {
+ case NativeBridgeAction::kUnload:
+ UnloadNativeBridge();
+ is_native_bridge_loaded_ = false;
+ break;
- case NativeBridgeAction::kInitialize:
- InitializeNativeBridge(env, isa);
- break;
+ case NativeBridgeAction::kInitialize:
+ InitializeNativeBridge(env, isa);
+ break;
+ }
}
// Create the thread pool.
@@ -889,8 +895,7 @@
// Runtime::Start():
// DidForkFromZygote(kInitialize) -> try to initialize any native bridge given.
// No-op wrt native bridge.
- native_bridge_library_filename_ = options->native_bridge_library_filename_;
- LoadNativeBridge(native_bridge_library_filename_);
+ is_native_bridge_loaded_ = LoadNativeBridge(options->native_bridge_library_filename_);
VLOG(startup) << "Runtime::Init exiting";
return true;
diff --git a/runtime/runtime.h b/runtime/runtime.h
index f3bea17..bfa7d72 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -635,14 +635,16 @@
bool implicit_so_checks_; // StackOverflow checks are implicit.
bool implicit_suspend_checks_; // Thread suspension checks are implicit.
- // The filename to the native bridge library. If this is not empty the native bridge will be
- // initialized and loaded from the given file (initialized and available). An empty value means
- // that there's no native bridge (initialized but not available).
+ // Whether or not a native bridge has been loaded.
//
// The native bridge allows running native code compiled for a foreign ISA. The way it works is,
// if standard dlopen fails to load native library associated with native activity, it calls to
// the native bridge to load it and then gets the trampoline for the entry to native activity.
- std::string native_bridge_library_filename_;
+ //
+ // The option 'native_bridge_library_filename' specifies the name of the native bridge.
+ // When non-empty the native bridge will be loaded from the given file. An empty value means
+ // that there's no native bridge.
+ bool is_native_bridge_loaded_;
DISALLOW_COPY_AND_ASSIGN(Runtime);
};