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

Commit c78840c7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add a list to track unfinished tasks and dumpStackTraces" into qt-dev

parents 8052d14b a4d089f2
Loading
Loading
Loading
Loading
+44 −14
Original line number Diff line number Diff line
@@ -22,9 +22,10 @@ import android.util.Slog;

import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.Preconditions;
import com.android.server.am.ActivityManagerService;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -47,6 +48,8 @@ public class SystemServerInitThreadPool {
    private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(4,
            "system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND);

    private List<String> mPendingTasks = new ArrayList<>();

    public static synchronized SystemServerInitThreadPool get() {
        if (sInstance == null) {
            sInstance = new SystemServerInitThreadPool();
@@ -57,19 +60,26 @@ public class SystemServerInitThreadPool {
    }

    public Future<?> submit(Runnable runnable, String description) {
        if (IS_DEBUGGABLE) {
        synchronized (mPendingTasks) {
            mPendingTasks.add(description);
        }
        return mService.submit(() -> {
            if (IS_DEBUGGABLE) {
                Slog.d(TAG, "Started executing " + description);
            }
            try {
                runnable.run();
            } catch (RuntimeException e) {
                Slog.e(TAG, "Failure in " + description + ": " + e, e);
                throw e;
            }
            synchronized (mPendingTasks) {
                mPendingTasks.remove(description);
            }
            if (IS_DEBUGGABLE) {
                Slog.d(TAG, "Finished executing " + description);
            });
            }
        return mService.submit(runnable);
        });
    }

    static synchronized void shutdown() {
@@ -81,16 +91,36 @@ public class SystemServerInitThreadPool {
                        TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                dumpStackTraces();
                throw new IllegalStateException(TAG + " init interrupted");
            }
            if (!terminated) {
                // dump stack must be called before shutdownNow() to collect stacktrace of threads
                // in the thread pool.
                dumpStackTraces();
            }
            List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow();
            if (!terminated) {
                final List<String> copy = new ArrayList<>();
                synchronized (sInstance.mPendingTasks) {
                    copy.addAll(sInstance.mPendingTasks);
                }
                throw new IllegalStateException("Cannot shutdown. Unstarted tasks "
                        + unstartedRunnables);
                        + unstartedRunnables + " Unfinished tasks " + copy);
            }
            sInstance.mService = null; // Make mService eligible for GC
            sInstance.mPendingTasks = null;
            Slog.d(TAG, "Shutdown successful");
        }
    }

    /**
     * A helper function to call ActivityManagerService.dumpStackTraces().
     */
    private static void dumpStackTraces() {
        final ArrayList<Integer> pids = new ArrayList<>();
        pids.add(Process.myPid());
        ActivityManagerService.dumpStackTraces(
                pids, null, null, null);
    }
}