This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]