1 /* Multi-threaded test for resolver initialization.
2    Copyright (C) 2017-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <netdb.h>
20 #include <resolv.h>
21 #include <stdlib.h>
22 #include <support/check.h>
23 #include <support/support.h>
24 #include <support/xthread.h>
25 
26 /* Whether name lookups succeed does not really matter.  We use this
27    to trigger initialization of the resolver.  */
28 static const char *test_hostname = "www.gnu.org";
29 
30 /* The different initialization methods.  */
31 enum test_type { init, byname, gai };
32 enum { type_count = 3 };
33 
34 /* Thread function.  Perform a few resolver options.  */
35 static void *
thread_func(void * closure)36 thread_func (void *closure)
37 {
38   enum test_type *ptype = closure;
39   /* Perform a few calls to the requested operation.  */
40   TEST_VERIFY (*ptype >= 0);
41   TEST_VERIFY (*ptype < (int) type_count);
42   for (int i = 0; i < 3; ++i)
43     switch (*ptype)
44       {
45       case init:
46 	res_init ();
47 	break;
48       case byname:
49 	gethostbyname (test_hostname);
50 	break;
51       case gai:
52 	{
53 	  struct addrinfo hints = { 0, };
54 	  struct addrinfo *ai = NULL;
55 	  if (getaddrinfo (test_hostname, "80", &hints, &ai) == 0)
56 	    freeaddrinfo (ai);
57 	}
58 	break;
59       }
60   free (ptype);
61   return NULL;
62 }
63 
64 static int
do_test(void)65 do_test (void)
66 {
67   /* Start a small number of threads which perform resolver
68      operations.  */
69   enum { thread_count = 30 };
70 
71   pthread_t threads[thread_count];
72   for (int i = 0; i < thread_count; ++i)
73     {
74       enum test_type *ptype = xmalloc (sizeof (*ptype));
75       *ptype = i % type_count;
76       threads[i] = xpthread_create (NULL, thread_func, ptype);
77     }
78   for (int i = 0; i < type_count; ++i)
79     {
80       enum test_type *ptype = xmalloc (sizeof (*ptype));
81       *ptype = i;
82       thread_func (ptype);
83     }
84   for (int i = 0; i < thread_count; ++i)
85     xpthread_join (threads[i]);
86   return 0;
87 }
88 
89 #include <support/test-driver.c>
90