1 .\" Copyright (c) 2009 Petr Baudis <pasky@suse.cz>
2 .\" and clean-ups and additions (C) Copyright 2010 Michael Kerrisk
3 .\" <mtk.manpages@gmail.com>
5 .\" %%%LICENSE_START(VERBATIM)
6 .\" Permission is granted to make and distribute verbatim copies of this
7 .\" manual provided the copyright notice and this permission notice are
8 .\" preserved on all copies.
10 .\" Permission is granted to copy and distribute modified versions of this
11 .\" manual under the conditions for verbatim copying, provided that the
12 .\" entire resulting derived work is distributed under the terms of a
13 .\" permission notice identical to this one.
15 .\" Since the Linux kernel and libraries are constantly changing, this
16 .\" manual page may be incorrect or out-of-date. The author(s) assume no
17 .\" responsibility for errors or omissions, or for damages resulting from
18 .\" the use of the information contained herein. The author(s) may not
19 .\" have taken the same level of care in the production of this manual,
20 .\" which is licensed free of charge, as they might when working
23 .\" Formatted or processed versions of this manual, if unaccompanied by
24 .\" the source, must acknowledge the copyright and authors of this work.
27 .\" References: http://people.redhat.com/drepper/asynchnl.pdf,
28 .\" http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html
30 .TH GETADDRINFO_A 3 2021-03-22 "GNU" "Linux Programmer's Manual"
32 getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous
33 network address and service translation
36 .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
39 .BI "int getaddrinfo_a(int " mode ", struct gaicb *" list [restrict],
40 .BI " int " nitems ", struct sigevent *restrict " sevp );
41 .BI "int gai_suspend(const struct gaicb *const " list "[], int " nitems ,
42 .BI " const struct timespec *" timeout );
44 .BI "int gai_error(struct gaicb *" req );
45 .BI "int gai_cancel(struct gaicb *" req );
47 Link with \fI\-lanl\fP.
52 function performs the same task as
54 but allows multiple name look-ups to be performed asynchronously,
55 with optional notification on completion of look-up operations.
59 argument has one of the following values:
62 Perform the look-ups synchronously.
63 The call blocks until the look-ups have completed.
66 Perform the look-ups asynchronously.
67 The call returns immediately,
68 and the requests are resolved in the background.
69 See the discussion of the
75 specifies the look-up requests to process.
78 argument specifies the number of elements in
80 The requested look-up operations are started in parallel.
84 Each request is described by a
86 structure, defined as follows:
92 const char *ar_service;
93 const struct addrinfo *ar_request;
94 struct addrinfo *ar_result;
99 The elements of this structure correspond to the arguments of
109 argument, identifying an Internet host and a service.
112 element corresponds to the
114 argument, specifying the criteria for selecting
115 the returned socket address structures.
120 argument; you do not need to initialize this element,
121 it will be automatically set when the request
125 structure referenced by the last two elements is described in
132 notifications about resolved requests
133 can be obtained by employing the
135 structure pointed to by the
138 For the definition and general details of this structure, see
141 .I sevp\->sigev_notify
142 field can have the following values:
145 Don't provide any notification.
148 When a look-up completes, generate the signal
158 structure will be set to
160 .\" si_pid and si_uid are also set, to the values of the calling process,
161 .\" which doesn't provide useful information, so we'll skip mentioning it.
164 When a look-up completes, invoke
165 .I sigev_notify_function
166 as if it were the start function of a new thread.
175 it may be useful to point
176 .IR sevp\->sigev_value.sival_ptr
182 function suspends execution of the calling thread,
183 waiting for the completion of one or more requests in the array
187 argument specifies the size of the array
189 The call blocks until one of the following occurs:
191 One or more of the operations in
195 The call is interrupted by a signal that is caught.
197 The time interval specified in
200 This argument specifies a timeout in seconds plus nanoseconds (see
207 is NULL, then the call blocks indefinitely
208 (until one of the events above occurs).
210 No explicit indication of which request was completed is given;
211 you must determine which request(s) have completed by iterating with
213 over the list of requests.
217 function returns the status of the request
221 if the request was not completed yet,
222 0 if it was handled successfully,
223 or an error code if the request could not be resolved.
227 function cancels the request
229 If the request has been canceled successfully,
230 the error status of the request will be set to
232 and normal asynchronous notification will be performed.
233 The request cannot be canceled if it is currently being processed;
234 in that case, it will be handled as if
236 has never been called.
239 is NULL, an attempt is made to cancel all outstanding requests
240 that the process has made.
244 function returns 0 if all of the requests have been enqueued successfully,
245 or one of the following nonzero error codes:
248 The resources necessary to enqueue the look-up requests were not available.
249 The application may check the error status of each
250 request to determine which ones failed.
261 function returns 0 if at least one of the listed requests has been completed.
262 Otherwise, it returns one of the following nonzero error codes:
265 The given timeout expired before any of the requests could be completed.
268 There were no actual requests given to the function.
271 A signal has interrupted the function.
272 Note that this interruption might have been
273 caused by signal notification of some completed look-up request.
279 for an unfinished look-up request,
280 0 for a successfully completed look-up
281 (as described above), one of the error codes that could be returned by
285 if the request has been canceled explicitly before it could be finished.
289 function can return one of these values:
292 The request has been canceled successfully.
295 The request has not been canceled.
298 The request has already completed.
302 function translates these error codes to a human readable string,
303 suitable for error reporting.
305 For an explanation of the terms used in this section, see
313 Interface Attribute Value
315 .BR getaddrinfo_a (),
319 T} Thread safety MT-Safe
325 These functions are GNU extensions;
326 they first appeared in glibc in version 2.2.3.
330 was modeled after the
334 Two examples are provided: a simple example that resolves
335 several requests in parallel synchronously, and a complex example
336 showing some of the asynchronous capabilities.
337 .SS Synchronous example
338 The program below simply resolves several hostnames in parallel,
339 giving a speed-up compared to resolving the hostnames sequentially using
341 The program might be used like this:
345 $ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP
346 ftp.us.kernel.org: 128.30.2.36
347 enoent.linuxfoundation.org: Name or service not known
348 gnu.cz: 87.236.197.13
352 Here is the program source code
362 main(int argc, char *argv[])
365 struct gaicb *reqs[argc \- 1];
366 char host[NI_MAXHOST];
367 struct addrinfo *res;
370 fprintf(stderr, "Usage: %s HOST...\en", argv[0]);
374 for (int i = 0; i < argc \- 1; i++) {
375 reqs[i] = malloc(sizeof(*reqs[0]));
376 if (reqs[i] == NULL) {
380 memset(reqs[i], 0, sizeof(*reqs[0]));
381 reqs[i]\->ar_name = argv[i + 1];
384 ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
386 fprintf(stderr, "getaddrinfo_a() failed: %s\en",
391 for (int i = 0; i < argc \- 1; i++) {
392 printf("%s: ", reqs[i]\->ar_name);
393 ret = gai_error(reqs[i]);
395 res = reqs[i]\->ar_result;
397 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
399 NULL, 0, NI_NUMERICHOST);
401 fprintf(stderr, "getnameinfo() failed: %s\en",
408 puts(gai_strerror(ret));
414 .SS Asynchronous example
415 This example shows a simple interactive
418 The notification facility is not demonstrated.
420 An example session might look like this:
425 > a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
427 [2] gnu.cz: Request not canceled
429 [00] ftp.us.kernel.org: Finished
431 [00] ftp.us.kernel.org: 216.165.129.139
432 [01] enoent.linuxfoundation.org: Processing request in progress
433 [02] gnu.cz: 87.236.197.13
435 [00] ftp.us.kernel.org: 216.165.129.139
436 [01] enoent.linuxfoundation.org: Name or service not known
437 [02] gnu.cz: 87.236.197.13
441 The program source is as follows:
450 static struct gaicb **reqs = NULL;
451 static int nreqs = 0;
456 static char buf[256];
458 fputs("> ", stdout); fflush(stdout);
459 if (fgets(buf, sizeof(buf), stdin) == NULL)
462 if (buf[strlen(buf) \- 1] == \(aq\en\(aq)
463 buf[strlen(buf) \- 1] = 0;
468 /* Add requests for specified hostnames. */
472 int nreqs_base = nreqs;
476 while ((host = strtok(NULL, " "))) {
478 reqs = realloc(reqs, sizeof(reqs[0]) * nreqs);
480 reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0]));
481 reqs[nreqs \- 1]\->ar_name = strdup(host);
484 /* Queue nreqs_base..nreqs requests. */
486 ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
487 nreqs \- nreqs_base, NULL);
489 fprintf(stderr, "getaddrinfo_a() failed: %s\en",
495 /* Wait until at least one of specified requests completes. */
501 struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs));
502 /* NULL elements are ignored by gai_suspend(). */
504 while ((id = strtok(NULL, " ")) != NULL) {
508 printf("Bad request number: %s\en", id);
512 wait_reqs[n] = reqs[n];
515 ret = gai_suspend(wait_reqs, nreqs, NULL);
517 printf("gai_suspend(): %s\en", gai_strerror(ret));
521 for (int i = 0; i < nreqs; i++) {
522 if (wait_reqs[i] == NULL)
525 ret = gai_error(reqs[i]);
526 if (ret == EAI_INPROGRESS)
529 printf("[%02d] %s: %s\en", i, reqs[i]\->ar_name,
530 ret == 0 ? "Finished" : gai_strerror(ret));
534 /* Cancel specified requests. */
536 cancel_requests(void)
541 while ((id = strtok(NULL, " ")) != NULL) {
545 printf("Bad request number: %s\en", id);
549 ret = gai_cancel(reqs[n]);
550 printf("[%s] %s: %s\en", id, reqs[atoi(id)]\->ar_name,
555 /* List all requests. */
560 char host[NI_MAXHOST];
561 struct addrinfo *res;
563 for (int i = 0; i < nreqs; i++) {
564 printf("[%02d] %s: ", i, reqs[i]\->ar_name);
565 ret = gai_error(reqs[i]);
568 res = reqs[i]\->ar_result;
570 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
572 NULL, 0, NI_NUMERICHOST);
574 fprintf(stderr, "getnameinfo() failed: %s\en",
580 puts(gai_strerror(ret));
586 main(int argc, char *argv[])
591 while ((cmdline = getcmd()) != NULL) {
592 cmd = strtok(cmdline, " ");
611 fprintf(stderr, "Bad command: %c\en", cmd[0]);