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

Commit 5386f494 authored by Luke Huang's avatar Luke Huang
Browse files

Fix cancellation race problem for aysnc DNS API

This problem might cause double-close fd and result in app crash
or unexpected behaviour

Bug: 129317069
Test: atest DnsResolverTest
      manual test with delaying response callback/cancel
Change-Id: I223234f527edafc51d34fa6be390419c05def8d8
parent eea398a6
Loading
Loading
Loading
Loading
+36 −26
Original line number Diff line number Diff line
@@ -205,6 +205,7 @@ public final class DnsResolver {
        if (cancellationSignal != null && cancellationSignal.isCanceled()) {
            return;
        }
        final Object lock = new Object();
        final FileDescriptor queryfd;
        try {
            queryfd = resNetworkSend((network != null
@@ -214,8 +215,8 @@ public final class DnsResolver {
            return;
        }

        maybeAddCancellationSignal(cancellationSignal, queryfd);
        registerFDListener(executor, queryfd, callback);
        maybeAddCancellationSignal(cancellationSignal, queryfd, lock);
        registerFDListener(executor, queryfd, callback, cancellationSignal, lock);
    }

    /**
@@ -242,6 +243,7 @@ public final class DnsResolver {
        if (cancellationSignal != null && cancellationSignal.isCanceled()) {
            return;
        }
        final Object lock = new Object();
        final FileDescriptor queryfd;
        try {
            queryfd = resNetworkQuery((network != null
@@ -251,17 +253,22 @@ public final class DnsResolver {
            return;
        }

        maybeAddCancellationSignal(cancellationSignal, queryfd);
        registerFDListener(executor, queryfd, callback);
        maybeAddCancellationSignal(cancellationSignal, queryfd, lock);
        registerFDListener(executor, queryfd, callback, cancellationSignal, lock);
    }

    private <T> void registerFDListener(@NonNull Executor executor,
            @NonNull FileDescriptor queryfd, @NonNull AnswerCallback<T> answerCallback) {
            @NonNull FileDescriptor queryfd, @NonNull AnswerCallback<T> answerCallback,
            @Nullable CancellationSignal cancellationSignal, @NonNull Object lock) {
        Looper.getMainLooper().getQueue().addOnFileDescriptorEventListener(
                queryfd,
                FD_EVENTS,
                (fd, events) -> {
                    executor.execute(() -> {
                        synchronized (lock) {
                            if (cancellationSignal != null && cancellationSignal.isCanceled()) {
                                return;
                            }
                            byte[] answerbuf = null;
                            try {
                                answerbuf = resNetworkResult(fd);
@@ -277,6 +284,7 @@ public final class DnsResolver {
                            } catch (ParseException e) {
                                answerCallback.onParseException(e);
                            }
                        }
                    });
                    // Unregister this fd listener
                    return 0;
@@ -284,13 +292,15 @@ public final class DnsResolver {
    }

    private void maybeAddCancellationSignal(@Nullable CancellationSignal cancellationSignal,
            @NonNull FileDescriptor queryfd) {
            @NonNull FileDescriptor queryfd, @NonNull Object lock) {
        if (cancellationSignal == null) return;
        cancellationSignal.setOnCancelListener(
                () -> {
        cancellationSignal.setOnCancelListener(() -> {
            synchronized (lock)  {
                if (!queryfd.valid()) return;
                Looper.getMainLooper().getQueue()
                        .removeOnFileDescriptorEventListener(queryfd);
                resNetworkCancel(queryfd);
            }
        });
    }

+2 −0
Original line number Diff line number Diff line
@@ -470,6 +470,7 @@ static jbyteArray android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz,
    std::vector<uint8_t> buf(MAXPACKETSIZE, 0);

    int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE);
    jniSetFileDescriptorOfFD(env, javaFd, -1);
    if (res < 0) {
        throwErrnoException(env, "resNetworkResult", -res);
        return nullptr;
@@ -490,6 +491,7 @@ static jbyteArray android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz,
static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobject javaFd) {
    int fd = jniGetFDFromFileDescriptor(env, javaFd);
    resNetworkCancel(fd);
    jniSetFileDescriptorOfFD(env, javaFd, -1);
}

static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) {