1 .\" Copyright (c) 2009 Petr Baudis <pasky@suse.cz>
2 .\" and clean-ups and additions (C) 2010 Michael Kerrisk <mtk.manpages@gmail.com>
4 .\" %%%LICENSE_START(VERBATIM)
5 .\" Permission is granted to make and distribute verbatim copies of this
6 .\" manual provided the copyright notice and this permission notice are
7 .\" preserved on all copies.
9 .\" Permission is granted to copy and distribute modified versions of this
10 .\" manual under the conditions for verbatim copying, provided that the
11 .\" entire resulting derived work is distributed under the terms of a
12 .\" permission notice identical to this one.
14 .\" Since the Linux kernel and libraries are constantly changing, this
15 .\" manual page may be incorrect or out-of-date. The author(s) assume no
16 .\" responsibility for errors or omissions, or for damages resulting from
17 .\" the use of the information contained herein. The author(s) may not
18 .\" have taken the same level of care in the production of this manual,
19 .\" which is licensed free of charge, as they might when working
22 .\" Formatted or processed versions of this manual, if unaccompanied by
23 .\" the source, must acknowledge the copyright and authors of this work.
26 .\" References: http://people.redhat.com/drepper/asynchnl.pdf,
27 .\" http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html
29 .TH GETADDRINFO_A 3 2014-05-28 "GNU" "Linux Programmer's Manual"
31 getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous
32 network address and service translation
35 .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
38 .BI "int getaddrinfo_a(int " "mode" ", struct gaicb *" "list[]" ,
39 .BI " int " "nitems" ", struct sigevent *" "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" );
46 .BI "int gai_cancel(struct gaicb *" "req" );
48 Link with \fI\-lanl\fP.
53 function performs the same task as
55 but allows multiple name look-ups to be performed asynchronously,
56 with optional notification on completion of look-up operations.
60 argument has one of the following values:
63 Perform the look-ups synchronously.
64 The call blocks until the look-ups have completed.
67 Perform the look-ups asynchronously.
68 The call returns immediately,
69 and the requests are resolved in the background.
70 See the discussion of the
76 specifies the look-up requests to process.
79 argument specifies the number of elements in
81 The requested look-up operations are started in parallel.
85 Each request is described by a
87 structure, defined as follows:
93 const char *ar_service;
94 const struct addrinfo *ar_request;
95 struct addrinfo *ar_result;
100 The elements of this structure correspond to the arguments of
110 argument, identifying an Internet host and a service.
113 element corresponds to the
115 argument, specifying the criteria for selecting
116 the returned socket address structures.
121 argument; you do not need to initialize this element,
122 it will be automatically set when the request
126 structure referenced by the last two elements is described in
133 notifications about resolved requests
134 can be obtained by employing the
136 structure pointed to by the
139 For the definition and general details of this structure, see
142 .I sevp\->sigev_notify
143 field can have the following values:
146 Don't provide any notification.
149 When a look-up completes, generate the signal
159 structure will be set to
161 .\" si_pid and si_uid are also set, to the values of the calling process,
162 .\" which doesn't provide useful information, so we'll skip mentioning it.
165 When a look-up completes, invoke
166 .I sigev_notify_function
167 as if it were the start function of a new thread.
176 it may be useful to point
177 .IR sevp\->sigev_value.sival_ptr
183 function suspends execution of the calling thread,
184 waiting for the completion of one or more requests in the array
188 argument specifies the size of the array
190 The call blocks until one of the following occurs:
192 One or more of the operations in
196 The call is interrupted by a signal that is caught.
198 The time interval specified in
201 This argument specifies a timeout in seconds plus nanoseconds (see
208 is NULL, then the call blocks indefinitely
209 (until one of the events above occurs).
211 No explicit indication of which request was completed is given;
212 you must determine which request(s) have completed by iterating with
214 over the list of requests.
218 function returns the status of the request
222 if the request was not completed yet,
223 0 if it was handled successfully,
224 or an error code if the request could not be resolved.
228 function cancels the request
230 If the request has been canceled successfully,
231 the error status of the request will be set to
233 and normal asynchronous notification will be performed.
234 The request cannot be canceled if it is currently being processed;
235 in that case, it will be handled as if
237 has never been called.
240 is NULL, an attempt is made to cancel all outstanding requests
241 that the process has made.
245 function returns 0 if all of the requests have been enqueued successfully,
246 or one of the following nonzero error codes:
249 The resources necessary to enqueue the look-up requests were not available.
250 The application may check the error status of each
251 request to determine which ones failed.
262 function returns 0 if at least one of the listed requests has been completed.
263 Otherwise, it returns one of the following nonzero error codes:
266 The given timeout expired before any of the requests could be completed.
269 There were no actual requests given to the function.
272 A signal has interrupted the function.
273 Note that this interruption might have been
274 caused by signal notification of some completed look-up request.
280 for an unfinished look-up request,
281 0 for a successfully completed look-up
282 (as described above), one of the error codes that could be returned by
286 if the request has been canceled explicitly before it could be finished.
290 function can return one of these values:
293 The request has been canceled successfully.
296 The request has not been canceled.
299 The request has already completed.
303 function translates these error codes to a human readable string,
304 suitable for error reporting.
306 These functions are GNU extensions;
307 they first appeared in glibc in version 2.2.3.
311 was modeled after the
315 Two examples are provided: a simple example that resolves
316 several requests in parallel synchronously, and a complex example
317 showing some of the asynchronous capabilities.
318 .SS Synchronous example
319 The program below simply resolves several hostnames in parallel,
320 giving a speed-up compared to resolving the hostnames sequentially using
322 The program might be used like this:
326 $ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP
327 ftp.us.kernel.org: 128.30.2.36
328 enoent.linuxfoundation.org: Name or service not known
329 gnu.cz: 87.236.197.13
333 Here is the program source code
343 main(int argc, char *argv[])
346 struct gaicb *reqs[argc \- 1];
347 char host[NI_MAXHOST];
348 struct addrinfo *res;
351 fprintf(stderr, "Usage: %s HOST...\\n", argv[0]);
355 for (i = 0; i < argc \- 1; i++) {
356 reqs[i] = malloc(sizeof(*reqs[0]));
357 if (reqs[i] == NULL) {
361 memset(reqs[i], 0, sizeof(*reqs[0]));
362 reqs[i]\->ar_name = argv[i + 1];
365 ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
367 fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
372 for (i = 0; i < argc \- 1; i++) {
373 printf("%s: ", reqs[i]\->ar_name);
374 ret = gai_error(reqs[i]);
376 res = reqs[i]\->ar_result;
378 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
380 NULL, 0, NI_NUMERICHOST);
382 fprintf(stderr, "getnameinfo() failed: %s\\n",
389 puts(gai_strerror(ret));
395 .SS Asynchronous example
396 This example shows a simple interactive
399 The notification facility is not demonstrated.
401 An example session might look like this:
406 > a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
408 [2] gnu.cz: Request not canceled
410 [00] ftp.us.kernel.org: Finished
412 [00] ftp.us.kernel.org: 216.165.129.139
413 [01] enoent.linuxfoundation.org: Processing request in progress
414 [02] gnu.cz: 87.236.197.13
416 [00] ftp.us.kernel.org: 216.165.129.139
417 [01] enoent.linuxfoundation.org: Name or service not known
418 [02] gnu.cz: 87.236.197.13
422 The program source is as follows:
431 static struct gaicb **reqs = NULL;
432 static int nreqs = 0;
437 static char buf[256];
439 fputs("> ", stdout); fflush(stdout);
440 if (fgets(buf, sizeof(buf), stdin) == NULL)
443 if (buf[strlen(buf) \- 1] == \(aq\\n\(aq)
444 buf[strlen(buf) \- 1] = 0;
449 /* Add requests for specified hostnames */
453 int nreqs_base = nreqs;
457 while ((host = strtok(NULL, " "))) {
459 reqs = realloc(reqs, nreqs * sizeof(reqs[0]));
461 reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0]));
462 reqs[nreqs \- 1]\->ar_name = strdup(host);
465 /* Queue nreqs_base..nreqs requests. */
467 ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
468 nreqs \- nreqs_base, NULL);
470 fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
476 /* Wait until at least one of specified requests completes */
482 struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs));
483 /* NULL elements are ignored by gai_suspend(). */
485 while ((id = strtok(NULL, " ")) != NULL) {
489 printf("Bad request number: %s\\n", id);
493 wait_reqs[n] = reqs[n];
496 ret = gai_suspend(wait_reqs, nreqs, NULL);
498 printf("gai_suspend(): %s\\n", gai_strerror(ret));
502 for (i = 0; i < nreqs; i++) {
503 if (wait_reqs[i] == NULL)
506 ret = gai_error(reqs[i]);
507 if (ret == EAI_INPROGRESS)
510 printf("[%02d] %s: %s\\n", i, reqs[i]\->ar_name,
511 ret == 0 ? "Finished" : gai_strerror(ret));
515 /* Cancel specified requests */
517 cancel_requests(void)
522 while ((id = strtok(NULL, " ")) != NULL) {
526 printf("Bad request number: %s\\n", id);
530 ret = gai_cancel(reqs[n]);
531 printf("[%s] %s: %s\\n", id, reqs[atoi(id)]\->ar_name,
536 /* List all requests */
541 char host[NI_MAXHOST];
542 struct addrinfo *res;
544 for (i = 0; i < nreqs; i++) {
545 printf("[%02d] %s: ", i, reqs[i]\->ar_name);
546 ret = gai_error(reqs[i]);
549 res = reqs[i]\->ar_result;
551 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
553 NULL, 0, NI_NUMERICHOST);
555 fprintf(stderr, "getnameinfo() failed: %s\\n",
561 puts(gai_strerror(ret));
567 main(int argc, char *argv[])
572 while ((cmdline = getcmd()) != NULL) {
573 cmd = strtok(cmdline, " ");
592 fprintf(stderr, "Bad command: %c\\n", cmd[0]);
608 This page is part of release 3.68 of the Linux
611 A description of the project,
612 information about reporting bugs,
613 and the latest version of this page,
615 \%http://www.kernel.org/doc/man\-pages/.