This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: GAI_a question
Hi,
Alle 23:06, lunedì, 24. luglio 2006, hai scritto:
> The call in the new thread is:
>
> sigev->sigev_notify_function (sigev->sigev_value);
Thanks, this is what I thought it is, but apparently it doesn't pass the right
parameter.
Note that in the original file I sent, sigev_value was set to NULL and still I
got a non-NULL pointer in the thread creation function, which made it look
suspicious for me.
> The program you sent does not exercise a case where sigev_notify_function
> is used and the value of sigev_value can be seen. Are you saying it does
> not work right? Please show a test program that actually does what you say
> fails.
Reduced testcase attached (which actually fails for me). It writes out a bogus
error message about
ai_family not supported
and then a double-free is detected in freeaddrinfo(), so that I assume the
pointer I get is not the correct one.
In the original file, using the global pointer to the 'req' object, the IP
addresses were found and printed out correctly. But not when I set and
get 'req' from sigev->sigev_value.
Josef
#define _GNU_SOURCE
#include <stdio.h>
#include <netdb.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
static void print_address(struct addrinfo *res)
{
char hostname[64];
int ret;
printf("Address: flags=%i family=%i socktype=%i protocol=%i\n",
res->ai_flags, res->ai_family, res->ai_socktype, res->ai_protocol);
/* Display a single result */
ret = getnameinfo(res->ai_addr, res->ai_addrlen,
hostname, sizeof(hostname), NULL, 0, NI_NUMERICHOST);
if(ret)
{
printf("Error (gni %i): %s\n", ret, gai_strerror(ret));
return;
}
printf(" -> [%s]\n", hostname);
}
static void print_addresses(struct addrinfo *res)
{
struct addrinfo *ptr;
printf("Results (res: %p):\n", res);
/* Iterate over result list */
for(ptr = res; ptr; ptr = ptr->ai_next)
{
print_address(ptr);
}
freeaddrinfo(res);
}
static void check_error(struct gaicb *req)
{
int ret = gai_error(req);
if(ret)
{
if(ret != EAI_INPROGRESS)
{
printf("Error: %s\n", gai_strerror(ret));
}
}
}
static void found_thread(sigval_t arg)
{
printf("(found_thread) callback in new thread!\n");
struct gaicb *req;
printf("(found_thread) sigval as ptr: %p\n", arg.sival_ptr);
if(arg.sival_ptr)
{
req = (struct gaicb*)arg.sival_ptr;
printf("(found_thread) now check it...\n");
check_error(req);
print_addresses(req->ar_result);
}
exit(0);
}
int main(int argc, char *argv[])
{
const char *host;
int ret;
struct sigevent sigev;
struct gaicb *req;
if(argc == 1)
{
host = "localhost";
}
else
{
host = argv[1];
}
setbuf(stdout, NULL);
/* Create request */
req = (struct gaicb*)malloc(sizeof(struct gaicb));
req->ar_name = host;
req->ar_service = NULL;
req->ar_request = NULL;
req->ar_result = NULL;
sigev.sigev_notify = SIGEV_THREAD;
sigev.sigev_value.sival_ptr = req;
sigev.sigev_notify_function = found_thread;
sigev.sigev_notify_attributes = NULL;
printf("sigval as ptr: %p\n", sigev.sigev_value.sival_ptr);
/* Perform lookup */
ret = getaddrinfo_a(GAI_NOWAIT, &req, 1, &sigev);
if(ret)
{
/* An immediate (enqueueing) error occured */
printf("Error: %s\n", gai_strerror(ret));
}
printf("go sleep...\n");
sleep(10);
return 0;
}