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 2017-09-15 "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[]" ,
40 .BI " int " "nitems" ", struct sigevent *" "sevp" );
42 .BI "int gai_suspend(const struct gaicb * const " "list[]" ", int " "nitems" ,
43 .BI " const struct timespec *" "timeout" );
45 .BI "int gai_error(struct gaicb *" "req" );
47 .BI "int gai_cancel(struct gaicb *" "req" );
49 Link with \fI\-lanl\fP.
54 function performs the same task as
56 but allows multiple name look-ups to be performed asynchronously,
57 with optional notification on completion of look-up operations.
61 argument has one of the following values:
64 Perform the look-ups synchronously.
65 The call blocks until the look-ups have completed.
68 Perform the look-ups asynchronously.
69 The call returns immediately,
70 and the requests are resolved in the background.
71 See the discussion of the
77 specifies the look-up requests to process.
80 argument specifies the number of elements in
82 The requested look-up operations are started in parallel.
86 Each request is described by a
88 structure, defined as follows:
94 const char *ar_service;
95 const struct addrinfo *ar_request;
96 struct addrinfo *ar_result;
101 The elements of this structure correspond to the arguments of
111 argument, identifying an Internet host and a service.
114 element corresponds to the
116 argument, specifying the criteria for selecting
117 the returned socket address structures.
122 argument; you do not need to initialize this element,
123 it will be automatically set when the request
127 structure referenced by the last two elements is described in
134 notifications about resolved requests
135 can be obtained by employing the
137 structure pointed to by the
140 For the definition and general details of this structure, see
143 .I sevp\->sigev_notify
144 field can have the following values:
147 Don't provide any notification.
150 When a look-up completes, generate the signal
160 structure will be set to
162 .\" si_pid and si_uid are also set, to the values of the calling process,
163 .\" which doesn't provide useful information, so we'll skip mentioning it.
166 When a look-up completes, invoke
167 .I sigev_notify_function
168 as if it were the start function of a new thread.
177 it may be useful to point
178 .IR sevp\->sigev_value.sival_ptr
184 function suspends execution of the calling thread,
185 waiting for the completion of one or more requests in the array
189 argument specifies the size of the array
191 The call blocks until one of the following occurs:
193 One or more of the operations in
197 The call is interrupted by a signal that is caught.
199 The time interval specified in
202 This argument specifies a timeout in seconds plus nanoseconds (see
209 is NULL, then the call blocks indefinitely
210 (until one of the events above occurs).
212 No explicit indication of which request was completed is given;
213 you must determine which request(s) have completed by iterating with
215 over the list of requests.
219 function returns the status of the request
223 if the request was not completed yet,
224 0 if it was handled successfully,
225 or an error code if the request could not be resolved.
229 function cancels the request
231 If the request has been canceled successfully,
232 the error status of the request will be set to
234 and normal asynchronous notification will be performed.
235 The request cannot be canceled if it is currently being processed;
236 in that case, it will be handled as if
238 has never been called.
241 is NULL, an attempt is made to cancel all outstanding requests
242 that the process has made.
246 function returns 0 if all of the requests have been enqueued successfully,
247 or one of the following nonzero error codes:
250 The resources necessary to enqueue the look-up requests were not available.
251 The application may check the error status of each
252 request to determine which ones failed.
263 function returns 0 if at least one of the listed requests has been completed.
264 Otherwise, it returns one of the following nonzero error codes:
267 The given timeout expired before any of the requests could be completed.
270 There were no actual requests given to the function.
273 A signal has interrupted the function.
274 Note that this interruption might have been
275 caused by signal notification of some completed look-up request.
281 for an unfinished look-up request,
282 0 for a successfully completed look-up
283 (as described above), one of the error codes that could be returned by
287 if the request has been canceled explicitly before it could be finished.
291 function can return one of these values:
294 The request has been canceled successfully.
297 The request has not been canceled.
300 The request has already completed.
304 function translates these error codes to a human readable string,
305 suitable for error reporting.
307 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
323 These functions are GNU extensions;
324 they first appeared in glibc in version 2.2.3.
328 was modeled after the
332 Two examples are provided: a simple example that resolves
333 several requests in parallel synchronously, and a complex example
334 showing some of the asynchronous capabilities.
335 .SS Synchronous example
336 The program below simply resolves several hostnames in parallel,
337 giving a speed-up compared to resolving the hostnames sequentially using
339 The program might be used like this:
343 $ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP
344 ftp.us.kernel.org: 128.30.2.36
345 enoent.linuxfoundation.org: Name or service not known
346 gnu.cz: 87.236.197.13
350 Here is the program source code
360 main(int argc, char *argv[])
363 struct gaicb *reqs[argc \- 1];
364 char host[NI_MAXHOST];
365 struct addrinfo *res;
368 fprintf(stderr, "Usage: %s HOST...\\n", argv[0]);
372 for (i = 0; i < argc \- 1; i++) {
373 reqs[i] = malloc(sizeof(*reqs[0]));
374 if (reqs[i] == NULL) {
378 memset(reqs[i], 0, sizeof(*reqs[0]));
379 reqs[i]\->ar_name = argv[i + 1];
382 ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
384 fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
389 for (i = 0; i < argc \- 1; i++) {
390 printf("%s: ", reqs[i]\->ar_name);
391 ret = gai_error(reqs[i]);
393 res = reqs[i]\->ar_result;
395 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
397 NULL, 0, NI_NUMERICHOST);
399 fprintf(stderr, "getnameinfo() failed: %s\\n",
406 puts(gai_strerror(ret));
412 .SS Asynchronous example
413 This example shows a simple interactive
416 The notification facility is not demonstrated.
418 An example session might look like this:
423 > a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
425 [2] gnu.cz: Request not canceled
427 [00] ftp.us.kernel.org: Finished
429 [00] ftp.us.kernel.org: 216.165.129.139
430 [01] enoent.linuxfoundation.org: Processing request in progress
431 [02] gnu.cz: 87.236.197.13
433 [00] ftp.us.kernel.org: 216.165.129.139
434 [01] enoent.linuxfoundation.org: Name or service not known
435 [02] gnu.cz: 87.236.197.13
439 The program source is as follows:
448 static struct gaicb **reqs = NULL;
449 static int nreqs = 0;
454 static char buf[256];
456 fputs("> ", stdout); fflush(stdout);
457 if (fgets(buf, sizeof(buf), stdin) == NULL)
460 if (buf[strlen(buf) \- 1] == \(aq\\n\(aq)
461 buf[strlen(buf) \- 1] = 0;
466 /* Add requests for specified hostnames */
470 int nreqs_base = nreqs;
474 while ((host = strtok(NULL, " "))) {
476 reqs = realloc(reqs, nreqs * sizeof(reqs[0]));
478 reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0]));
479 reqs[nreqs \- 1]\->ar_name = strdup(host);
482 /* Queue nreqs_base..nreqs requests. */
484 ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
485 nreqs \- nreqs_base, NULL);
487 fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
493 /* Wait until at least one of specified requests completes */
499 struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs));
500 /* NULL elements are ignored by gai_suspend(). */
502 while ((id = strtok(NULL, " ")) != NULL) {
506 printf("Bad request number: %s\\n", id);
510 wait_reqs[n] = reqs[n];
513 ret = gai_suspend(wait_reqs, nreqs, NULL);
515 printf("gai_suspend(): %s\\n", gai_strerror(ret));
519 for (i = 0; i < nreqs; i++) {
520 if (wait_reqs[i] == NULL)
523 ret = gai_error(reqs[i]);
524 if (ret == EAI_INPROGRESS)
527 printf("[%02d] %s: %s\\n", i, reqs[i]\->ar_name,
528 ret == 0 ? "Finished" : gai_strerror(ret));
532 /* Cancel specified requests */
534 cancel_requests(void)
539 while ((id = strtok(NULL, " ")) != NULL) {
543 printf("Bad request number: %s\\n", id);
547 ret = gai_cancel(reqs[n]);
548 printf("[%s] %s: %s\\n", id, reqs[atoi(id)]\->ar_name,
553 /* List all requests */
558 char host[NI_MAXHOST];
559 struct addrinfo *res;
561 for (i = 0; i < nreqs; i++) {
562 printf("[%02d] %s: ", i, reqs[i]\->ar_name);
563 ret = gai_error(reqs[i]);
566 res = reqs[i]\->ar_result;
568 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
570 NULL, 0, NI_NUMERICHOST);
572 fprintf(stderr, "getnameinfo() failed: %s\\n",
578 puts(gai_strerror(ret));
584 main(int argc, char *argv[])
589 while ((cmdline = getcmd()) != NULL) {
590 cmd = strtok(cmdline, " ");
609 fprintf(stderr, "Bad command: %c\\n", cmd[0]);