Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a27fabe4 authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Enable fdtrack in system_server." am: 62d4abfd am: 7a3ca376

Change-Id: I8f0916438cdf5b762a25621bbc8809a5cba6f4bb
parents 16d8f3cc 7a3ca376
Loading
Loading
Loading
Loading
+58 −1
Original line number Diff line number Diff line
@@ -14,6 +14,12 @@
 * limitations under the License.
 */

#include <dlfcn.h>
#include <pthread.h>

#include <chrono>
#include <thread>

#include <jni.h>
#include <nativehelper/JNIHelp.h>

@@ -25,12 +31,17 @@
#include <sensorservicehidl/SensorManager.h>

#include <bionic/malloc.h>
#include <bionic/reserved_signals.h>

#include <android-base/properties.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/misc.h>
#include <utils/AndroidThreads.h>

using android::base::GetIntProperty;
using namespace std::chrono_literals;

namespace android {

static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
@@ -71,6 +82,49 @@ static void android_server_SystemServer_initZygoteChildHeapProfiling(JNIEnv* /*
    android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0);
}

static int get_current_max_fd() {
    // Not actually guaranteed to be the max, but close enough for our purposes.
    int fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
    LOG_ALWAYS_FATAL_IF(fd == -1, "failed to open /dev/null: %s", strerror(errno));
    close(fd);
    return fd;
}

static const char kFdLeakEnableThresholdProperty[] = "persist.sys.debug.fdtrack_enable_threshold";
static const char kFdLeakAbortThresholdProperty[] = "persist.sys.debug.fdtrack_abort_threshold";
static const char kFdLeakCheckIntervalProperty[] = "persist.sys.debug.fdtrack_interval";

static void android_server_SystemServer_spawnFdLeakCheckThread(JNIEnv*, jobject) {
    std::thread([]() {
        pthread_setname_np(pthread_self(), "FdLeakCheckThread");
        bool loaded = false;
        while (true) {
            const int enable_threshold = GetIntProperty(kFdLeakEnableThresholdProperty, 1024);
            const int abort_threshold = GetIntProperty(kFdLeakAbortThresholdProperty, 2048);
            const int check_interval = GetIntProperty(kFdLeakCheckIntervalProperty, 120);
            int max_fd = get_current_max_fd();
            if (max_fd > enable_threshold && !loaded) {
                loaded = true;
                ALOGE("fd count above threshold of %d, starting fd backtraces", enable_threshold);
                if (dlopen("libfdtrack.so", RTLD_GLOBAL) == nullptr) {
                    ALOGE("failed to load libfdtrack.so: %s", dlerror());
                }
            } else if (max_fd > abort_threshold) {
                raise(BIONIC_SIGNAL_FDTRACK);

                // Wait for a bit to allow fdtrack to dump backtraces to logcat.
                std::this_thread::sleep_for(5s);

                LOG_ALWAYS_FATAL(
                    "b/140703823: aborting due to fd leak: check logs for fd "
                    "backtraces");
            }

            std::this_thread::sleep_for(std::chrono::seconds(check_interval));
        }
    }).detach();
}

/*
 * JNI registration.
 */
@@ -80,6 +134,9 @@ static const JNINativeMethod gMethods[] = {
    { "startHidlServices", "()V", (void*) android_server_SystemServer_startHidlServices },
    { "initZygoteChildHeapProfiling", "()V",
      (void*) android_server_SystemServer_initZygoteChildHeapProfiling },
    { "spawnFdLeakCheckThread", "()V",
      (void*) android_server_SystemServer_spawnFdLeakCheckThread },

};

int register_android_server_SystemServer(JNIEnv* env)
+11 −0
Original line number Diff line number Diff line
@@ -353,6 +353,12 @@ public final class SystemServer {
     */
    private static native void initZygoteChildHeapProfiling();


    /**
     * Spawn a thread that monitors for fd leaks.
     */
    private static native void spawnFdLeakCheckThread();

    /**
     * The main entry point from zygote.
     */
@@ -484,6 +490,11 @@ public final class SystemServer {
                initZygoteChildHeapProfiling();
            }

            // Debug builds - spawn a thread to monitor for fd leaks.
            if (Build.IS_DEBUGGABLE) {
                spawnFdLeakCheckThread();
            }

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();