@@ -1637,6 +1637,119 @@ gaic_launch(struct event_base *base, struct evdns_base *dns_base)
1637
1637
++ pending ;
1638
1638
}
1639
1639
1640
+ static int allocated_chunks = 0 ;
1641
+
1642
+ static void *
1643
+ cnt_malloc (size_t sz )
1644
+ {
1645
+ allocated_chunks += 1 ;
1646
+ return malloc (sz );
1647
+ }
1648
+
1649
+ static void *
1650
+ cnt_realloc (void * old , size_t sz )
1651
+ {
1652
+ if (!old )
1653
+ allocated_chunks += 1 ;
1654
+ if (!sz )
1655
+ allocated_chunks -= 1 ;
1656
+ return realloc (old , sz );
1657
+ }
1658
+
1659
+ static void
1660
+ cnt_free (void * ptr )
1661
+ {
1662
+ allocated_chunks -= 1 ;
1663
+ return free (ptr );
1664
+ }
1665
+
1666
+ struct testleak_env_t {
1667
+ struct event_base * base ;
1668
+ struct evdns_base * dns_base ;
1669
+ struct evdns_request * req ;
1670
+ struct generic_dns_callback_result r ;
1671
+ };
1672
+
1673
+ static void *
1674
+ testleak_setup (const struct testcase_t * testcase )
1675
+ {
1676
+ struct testleak_env_t * env ;
1677
+
1678
+ allocated_chunks = 0 ;
1679
+ event_set_mem_functions (cnt_malloc , cnt_realloc , cnt_free );
1680
+ event_enable_debug_mode ();
1681
+
1682
+ env = calloc (1 , sizeof (struct testleak_env_t ));
1683
+ env -> base = event_base_new ();
1684
+ env -> dns_base = evdns_base_new (env -> base , 0 );
1685
+ env -> req = evdns_base_resolve_ipv4 (
1686
+ env -> dns_base , "example.com" , DNS_QUERY_NO_SEARCH ,
1687
+ generic_dns_callback , & env -> r );
1688
+ return env ;
1689
+ }
1690
+
1691
+ static int
1692
+ testleak_cleanup (const struct testcase_t * testcase , void * env_ )
1693
+ {
1694
+ int ok = 0 ;
1695
+ struct testleak_env_t * env = env_ ;
1696
+ /* FIXME: that's `1' because of event_debug_map_HT_GROW */
1697
+ tt_int_op (allocated_chunks , = = , 1 );
1698
+ ok = 1 ;
1699
+ end :
1700
+ if (env -> dns_base )
1701
+ evdns_base_free (env -> dns_base , 0 );
1702
+ if (env -> base )
1703
+ event_base_free (env -> base );
1704
+ if (env )
1705
+ free (env );
1706
+ return ok ;
1707
+ }
1708
+
1709
+ static struct testcase_setup_t testleak_funcs = {
1710
+ testleak_setup , testleak_cleanup
1711
+ };
1712
+
1713
+ static void
1714
+ test_dbg_leak_cancel (void * env_ )
1715
+ {
1716
+ /* cancel, loop, free/dns, free/base */
1717
+ struct testleak_env_t * env = env_ ;
1718
+ int send_err_shutdown = 1 ;
1719
+ evdns_cancel_request (env -> dns_base , env -> req );
1720
+ env -> req = 0 ;
1721
+
1722
+ /* `req` is freed in callback, that's why one loop is required. */
1723
+ event_base_loop (env -> base , EVLOOP_NONBLOCK );
1724
+
1725
+ /* send_err_shutdown means nothing as soon as our request is
1726
+ * already canceled */
1727
+ evdns_base_free (env -> dns_base , send_err_shutdown );
1728
+ env -> dns_base = 0 ;
1729
+ event_base_free (env -> base );
1730
+ env -> base = 0 ;
1731
+ }
1732
+
1733
+ static void
1734
+ test_dbg_leak_shutdown (void * env_ )
1735
+ {
1736
+ /* free/dns, loop, free/base */
1737
+ struct testleak_env_t * env = env_ ;
1738
+ int send_err_shutdown = 1 ;
1739
+
1740
+ /* `req` is freed both with `send_err_shutdown` and without it,
1741
+ * the only difference is `evdns_callback` call */
1742
+ env -> req = 0 ;
1743
+
1744
+ evdns_base_free (env -> dns_base , send_err_shutdown );
1745
+ env -> dns_base = 0 ;
1746
+
1747
+ /* `req` is freed in callback, that's why one loop is required */
1748
+ event_base_loop (env -> base , EVLOOP_NONBLOCK );
1749
+ event_base_free (env -> base );
1750
+ env -> base = 0 ;
1751
+ }
1752
+
1640
1753
static void
1641
1754
test_getaddrinfo_async_cancel_stress (void * ptr )
1642
1755
{
@@ -1714,6 +1827,9 @@ struct testcase_t dns_testcases[] = {
1714
1827
{ "getaddrinfo_cancel_stress" , test_getaddrinfo_async_cancel_stress ,
1715
1828
TT_FORK , NULL , NULL },
1716
1829
1830
+ { "leak_shutdown" , test_dbg_leak_shutdown , TT_FORK , & testleak_funcs , NULL },
1831
+ { "leak_cancel" , test_dbg_leak_cancel , TT_FORK , & testleak_funcs , NULL },
1832
+
1717
1833
END_OF_TESTCASES
1718
1834
};
1719
1835
0 commit comments