Test for thread creation failed
Netd should not crash when thread creation is failed on Asynchronous
API call.
Bug: 169105756
Test: run test w/ and w/o I9241a094653651e1bdda79eb753e7a53e5e51d8f
Change-Id: Iadd94eb661ea15adfffc8d8e31e7990901bedb28
diff --git a/tests/resolv_integration_test.cpp b/tests/resolv_integration_test.cpp
index 5d41a8a..67f59a6 100644
--- a/tests/resolv_integration_test.cpp
+++ b/tests/resolv_integration_test.cpp
@@ -2705,6 +2705,54 @@
EXPECT_EQ(1U, GetNumQueries(dns, host_name));
}
+// Run a large number of DNS queries through asynchronous API to create
+// thousands of threads in resolver to simulate the failure of thread creation
+// when memory per process is exhausted. (The current critical value is about
+// 84xx threads.)
+TEST_F(ResolverTest, Async_OutOfMemory) {
+ constexpr char host_name[] = "howdy.example.com.";
+ constexpr size_t AMOUNT_OF_UIDS = 40;
+ constexpr size_t MAX_QUERIES_PER_UID = 256;
+ constexpr size_t NUM_OF_QUERIES = AMOUNT_OF_UIDS * MAX_QUERIES_PER_UID;
+
+ test::DNSResponder dns;
+ StartDns(dns, {{host_name, ns_type::ns_t_a, "1.2.3.4"}});
+ ASSERT_TRUE(mDnsClient.SetResolversForNetwork());
+ dns.setDeferredResp(true);
+
+ std::vector<int> fds;
+ fds.reserve(NUM_OF_QUERIES);
+ bool send_query = true;
+ for (size_t i = 0; i < AMOUNT_OF_UIDS && send_query; i++) {
+ ScopedChangeUID scopedChangeUID(TEST_UID - i);
+ for (size_t j = 0; j < MAX_QUERIES_PER_UID; j++) {
+ int fd = resNetworkQuery(TEST_NETID, "howdy.example.com", ns_c_in, ns_t_a, 0);
+ if (fd >= 0) {
+ fds.emplace_back(fd);
+ } else {
+ send_query = false;
+ break;
+ }
+ }
+ }
+
+ dns.setDeferredResp(false);
+ EXPECT_EQ(NUM_OF_QUERIES, fds.size());
+ // TODO: AIBinder_DeathRecipient_new does not work (b/172178636), which
+ // should be fixed. Fortunately, netd crash is still detectable at the point
+ // of DumpResolverService() in TearDown(), where accesses mDnsClient. Also,
+ // the fds size will be less than NUM_OF_QUERIES in that case.
+
+ uint8_t buf[MAXPACKET];
+ int rcode;
+ for (auto fd : fds) {
+ memset(buf, 0, MAXPACKET);
+ getAsyncResponse(fd, &rcode, buf, MAXPACKET);
+ // The results of each DNS query are not examined, since they won't all
+ // succeed or all fail. Here we only focus on netd is crashed or not.
+ }
+}
+
// This test checks that the resolver should not generate the request containing OPT RR when using
// cleartext DNS. If we query the DNS server not supporting EDNS0 and it reponds with
// FORMERR_ON_EDNS, we will fallback to no EDNS0 and try again. If the server does no response, we