Merge "Fix cancellation race problem for aysnc DNS API" am: de6217b8e2
am: 829e409827
Change-Id: I633a592c7f46162268a759f84a77211443e9a04e
This commit is contained in:
@@ -205,6 +205,7 @@ public final class DnsResolver {
|
|||||||
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
|
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final Object lock = new Object();
|
||||||
final FileDescriptor queryfd;
|
final FileDescriptor queryfd;
|
||||||
try {
|
try {
|
||||||
queryfd = resNetworkSend((network != null
|
queryfd = resNetworkSend((network != null
|
||||||
@@ -214,8 +215,8 @@ public final class DnsResolver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeAddCancellationSignal(cancellationSignal, queryfd);
|
maybeAddCancellationSignal(cancellationSignal, queryfd, lock);
|
||||||
registerFDListener(executor, queryfd, callback);
|
registerFDListener(executor, queryfd, callback, cancellationSignal, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -242,6 +243,7 @@ public final class DnsResolver {
|
|||||||
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
|
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final Object lock = new Object();
|
||||||
final FileDescriptor queryfd;
|
final FileDescriptor queryfd;
|
||||||
try {
|
try {
|
||||||
queryfd = resNetworkQuery((network != null
|
queryfd = resNetworkQuery((network != null
|
||||||
@@ -251,31 +253,37 @@ public final class DnsResolver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeAddCancellationSignal(cancellationSignal, queryfd);
|
maybeAddCancellationSignal(cancellationSignal, queryfd, lock);
|
||||||
registerFDListener(executor, queryfd, callback);
|
registerFDListener(executor, queryfd, callback, cancellationSignal, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void registerFDListener(@NonNull Executor executor,
|
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(
|
Looper.getMainLooper().getQueue().addOnFileDescriptorEventListener(
|
||||||
queryfd,
|
queryfd,
|
||||||
FD_EVENTS,
|
FD_EVENTS,
|
||||||
(fd, events) -> {
|
(fd, events) -> {
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
byte[] answerbuf = null;
|
synchronized (lock) {
|
||||||
try {
|
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
|
||||||
answerbuf = resNetworkResult(fd);
|
return;
|
||||||
} catch (ErrnoException e) {
|
}
|
||||||
Log.e(TAG, "resNetworkResult:" + e.toString());
|
byte[] answerbuf = null;
|
||||||
answerCallback.onQueryException(e);
|
try {
|
||||||
return;
|
answerbuf = resNetworkResult(fd);
|
||||||
}
|
} catch (ErrnoException e) {
|
||||||
|
Log.e(TAG, "resNetworkResult:" + e.toString());
|
||||||
|
answerCallback.onQueryException(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
answerCallback.onAnswer(
|
answerCallback.onAnswer(
|
||||||
answerCallback.parser.parse(answerbuf));
|
answerCallback.parser.parse(answerbuf));
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
answerCallback.onParseException(e);
|
answerCallback.onParseException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Unregister this fd listener
|
// Unregister this fd listener
|
||||||
@@ -284,14 +292,16 @@ public final class DnsResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void maybeAddCancellationSignal(@Nullable CancellationSignal cancellationSignal,
|
private void maybeAddCancellationSignal(@Nullable CancellationSignal cancellationSignal,
|
||||||
@NonNull FileDescriptor queryfd) {
|
@NonNull FileDescriptor queryfd, @NonNull Object lock) {
|
||||||
if (cancellationSignal == null) return;
|
if (cancellationSignal == null) return;
|
||||||
cancellationSignal.setOnCancelListener(
|
cancellationSignal.setOnCancelListener(() -> {
|
||||||
() -> {
|
synchronized (lock) {
|
||||||
Looper.getMainLooper().getQueue()
|
if (!queryfd.valid()) return;
|
||||||
.removeOnFileDescriptorEventListener(queryfd);
|
Looper.getMainLooper().getQueue()
|
||||||
resNetworkCancel(queryfd);
|
.removeOnFileDescriptorEventListener(queryfd);
|
||||||
});
|
resNetworkCancel(queryfd);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DnsAddressAnswer extends DnsPacket {
|
private static class DnsAddressAnswer extends DnsPacket {
|
||||||
|
|||||||
@@ -470,6 +470,7 @@ static jbyteArray android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz,
|
|||||||
std::vector<uint8_t> buf(MAXPACKETSIZE, 0);
|
std::vector<uint8_t> buf(MAXPACKETSIZE, 0);
|
||||||
|
|
||||||
int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE);
|
int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE);
|
||||||
|
jniSetFileDescriptorOfFD(env, javaFd, -1);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
throwErrnoException(env, "resNetworkResult", -res);
|
throwErrnoException(env, "resNetworkResult", -res);
|
||||||
return nullptr;
|
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) {
|
static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobject javaFd) {
|
||||||
int fd = jniGetFDFromFileDescriptor(env, javaFd);
|
int fd = jniGetFDFromFileDescriptor(env, javaFd);
|
||||||
resNetworkCancel(fd);
|
resNetworkCancel(fd);
|
||||||
|
jniSetFileDescriptorOfFD(env, javaFd, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) {
|
static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) {
|
||||||
|
|||||||
Reference in New Issue
Block a user