1 .\" Copyright (c) 2009 Petr Baudis <pasky@suse.cz>
2 .\" and clean-ups and additions (C) 2010 Michael Kerrisk <mtk.manpages@gmail.com>
4 .\" Permission is granted to make and distribute verbatim copies of this
5 .\" manual provided the copyright notice and this permission notice are
6 .\" preserved on all copies.
8 .\" Permission is granted to copy and distribute modified versions of this
9 .\" manual under the conditions for verbatim copying, provided that the
10 .\" entire resulting derived work is distributed under the terms of a
11 .\" permission notice identical to this one.
13 .\" Since the Linux kernel and libraries are constantly changing, this
14 .\" manual page may be incorrect or out-of-date. The author(s) assume no
15 .\" responsibility for errors or omissions, or for damages resulting from
16 .\" the use of the information contained herein. The author(s) may not
17 .\" have taken the same level of care in the production of this manual,
18 .\" which is licensed free of charge, as they might when working
21 .\" Formatted or processed versions of this manual, if unaccompanied by
22 .\" the source, must acknowledge the copyright and authors of this work.
24 .\" References: http://people.redhat.com/drepper/asynchnl.pdf,
25 .\" http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html
27 .TH GETADDRINFO_A 3 2010-09-27 "GNU" "Linux Programmer's Manual"
29 getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous
30 network address and service translation
33 .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
36 .BI "int getaddrinfo_a(int " "mode" ", struct gaicb *" "list[]" ,
37 .BI " int " "nitems" ", struct sigevent *" "sevp" );
39 .BI "int gai_suspend(struct gaicb *" "list[]" ", int " "nitems" ,
40 .BI " struct timespec *" "timeout" );
42 .BI "int gai_error(struct gaicb *" "req" );
44 .BI "int gai_cancel(struct gaicb *" "req" );
46 Link with \fI\-lanl\fP.
51 function performs the same task as
53 but allows multiple name look-ups to be performed asynchronously,
54 with optional notification on completion of look-up operations.
58 argument has one of the following values:
61 Perform the look-ups synchronously.
62 The call blocks until the look-ups have completed.
65 Perform the look-ups asynchronously.
66 The call returns immediately,
67 and the requests are resolved in the background.
68 See the discussion of the
74 specifies the look-up requests to process.
77 argument specifies the number of elements in
79 The requested look-up operations are started in parallel.
83 Each request is described by a
85 structure, defined as follows:
91 const char *ar_service;
92 const struct addrinfo *ar_request;
93 struct addrinfo *ar_result;
98 The elements of this structure correspond to the arguments of
108 argument, identifying an Internet host and a service.
111 element corresponds to the
113 argument, specifying the criteria for selecting
114 the returned socket address structures.
119 argument; you do not need to initialize this element,
120 it will be automatically set when the request
124 structure referenced by the last two elements is described in
131 notifications about resolved requests
132 can be obtained by employing the
134 structure pointed to by the
137 For the definition and general details of this structure, see
140 .I sevp\->sigev_notify
141 field can have the following values:
144 Don't provide any notification.
147 When a look-up completes, generate the signal
157 structure will be set to
159 .\" si_pid and si_uid are also set, to the values of the calling process,
160 .\" which doesn't provide useful information, so we'll skip mentioning it.
163 When a look-up completes, invoke
164 .I sigev_notify_function
165 as if it were the start function of a new thread.
174 it may be useful to point
175 .IR sevp\->sigev_value.sival_ptr
181 function suspends execution of the calling thread,
182 waiting for the completion of one or more requests in the array
186 argument specifies the size of the array
188 The call blocks until one of the following occurs:
190 One or more of the operations in
194 The call is interrupted by a signal that is caught.
196 The time interval specified in
199 This argument specifies a timeout in seconds plus nanoseconds (see
206 is NULL, then the call blocks indefinitely
207 (until one of the events above occurs).
209 No explicit indication of which request was completed is given;
210 you must determine which request(s) have completed by iterating with
212 over the list of requests.
216 function returns the status of the request
220 if the request was not completed yet,
221 0 if it was handled successfully,
222 or an error code if the request could not be resolved.
226 function cancels the request
228 If the request has been canceled successfully,
229 the error status of the request will be set to
231 and normal asynchronous notification will be performed.
232 The request cannot be canceled if it is currently being processed;
233 in that case, it will be handled as if
235 has never been called.
238 is NULL, an attempt is made to cancel all outstanding requests
239 that the process has made.
243 function returns 0 if all of the requests have been enqueued successfully,
244 or one of the following nonzero error codes:
247 The resources necessary to enqueue the look-up requests were not available.
248 The application may check the error status of each
249 request to determine which ones failed.
260 function returns 0 if at least one of the listed requests has been completed.
261 Otherwise, it returns one of the following nonzero error codes:
264 The given timeout expired before any of the requests could be completed.
267 There were no actual requests given to the function.
270 A signal has interrupted the function.
271 Note that this interruption might have been
272 caused by signal notification of some completed look-up request.
278 for an unfinished look-up request,
279 0 for a successfully completed look-up
280 (as described above), one of the error codes that could be returned by
284 if the request has been canceled explicitly before it could be finished.
288 function can return one of these values:
291 The request has been canceled successfully.
294 The request has not been canceled.
297 The request has already completed.
301 function translates these error codes to a human readable string,
302 suitable for error reporting.
304 These functions are GNU extensions;
305 they first appeared in glibc in version 2.2.3.
309 was modeled after the
313 Two examples are provided: a simple example that resolves
314 several requests in parallel synchronously, and a complex example
315 showing some of the asynchronous capabilities.
316 .SS Synchronous Example
317 The program below simply resolves several hostnames in parallel,
318 giving a speed-up compared to resolving the hostnames sequentially using
320 The program might be used like this:
324 $ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP
325 ftp.us.kernel.org: 128.30.2.36
326 enoent.linuxfoundation.org: Name or service not known
327 gnu.cz: 87.236.197.13
331 Here is the program source code
341 main(int argc, char *argv[])
344 struct gaicb *reqs[argc \- 1];
345 char host[NI_MAXHOST];
346 struct addrinfo *res;
349 fprintf(stderr, "Usage: %s HOST...\\n", argv[0]);
353 for (i = 0; i < argc \- 1; i++) {
354 reqs[i] = malloc(sizeof(*reqs[0]));
355 if (reqs[i] == NULL) {
359 memset(reqs[i], 0, sizeof(*reqs[0]));
360 reqs[i]\->ar_name = argv[i + 1];
363 ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
365 fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
370 for (i = 0; i < argc \- 1; i++) {
371 printf("%s: ", reqs[i]\->ar_name);
372 ret = gai_error(reqs[i]);
374 res = reqs[i]\->ar_result;
376 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
378 NULL, 0, NI_NUMERICHOST);
380 fprintf(stderr, "getnameinfo() failed: %s\\n",
387 puts(gai_strerror(ret));
394 .SS Asynchronous Example
395 This example shows a simple interactive
398 The notification facility is not demonstrated.
400 An example session might look like like this:
405 > a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
407 [2] gnu.cz: Request not canceled
409 [00] ftp.us.kernel.org: Finished
411 [00] ftp.us.kernel.org: 216.165.129.139
412 [01] enoent.linuxfoundation.org: Processing request in progress
413 [02] gnu.cz: 87.236.197.13
415 [00] ftp.us.kernel.org: 216.165.129.139
416 [01] enoent.linuxfoundation.org: Name or service not known
417 [02] gnu.cz: 87.236.197.13
421 The program source goes 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]);