[ create a new paste ] login | about

Link: http://codepad.org/lyLVwfAd    [ raw code | fork ]

Lua, pasted on Jul 11:
local tquery = {"www.lua.org", "lua-users.org","localhost"}
if #arg > 0 then tquery = arg end
local n = #tquery

local ffi = require "ffi"
local bit = require "bit"
local anl = ffi.load "anl"

ffi.cdef[[
	char *strerror(int errnum);

	typedef struct {
		unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];
	} sigset_t;
	typedef int pid_t;

	enum {
	  SIGEV_SIGNAL = 0,
	  SIGEV_NONE,
	  SIGEV_THREAD,
	  SIGEV_THREAD_ID = 4
	};
	int sigemptyset(sigset_t *set);
	int sigaddset(sigset_t *set, int signum);
	int sigprocmask(int how, const sigset_t *restrict set,
			  sigset_t *restrict oset);
	extern int __libc_current_sigrtmin (void);

	struct signalfd_siginfo {
		uint32_t ssi_signo;   /* Signal number */
		int32_t  ssi_errno;   /* Error number (unused) */
		int32_t  ssi_code;    /* Signal code */
		uint32_t ssi_pid;     /* PID of sender */
		uint32_t ssi_uid;     /* Real UID of sender */
		int32_t  ssi_fd;      /* File descriptor (SIGIO) */
		uint32_t ssi_tid;     /* Kernel timer ID (POSIX timers)
		uint32_t ssi_band;    /* Band event (SIGIO) */
		uint32_t ssi_overrun; /* POSIX timer overrun count */
		uint32_t ssi_trapno;  /* Trap number that caused signal */
		int32_t  ssi_status;  /* Exit status or signal (SIGCHLD) */
		int32_t  ssi_int;     /* Integer sent by sigqueue(3) */
		uint64_t ssi_ptr;     /* Pointer sent by sigqueue(3) */
		uint64_t ssi_utime;   /* User CPU time consumed (SIGCHLD) */
		uint64_t ssi_stime;   /* System CPU time consumed (SIGCHLD) */
		uint64_t ssi_addr;    /* Address that generated signal (for hardware-generated signals) */
		uint8_t  pad[48];      /* Pad size to 128 bytes (allow for additional fields in the future) */
	};
	enum {
		SFD_CLOEXEC = 02000000,
		SFD_NONBLOCK = 04000
	};
	int signalfd(int fd, const sigset_t *mask, int flags);

	union sigval {          /* Data passed with notification */
		int     sival_int;         /* Integer value */
		void   *sival_ptr;         /* Pointer value */
	};

	struct sigevent {
		int          sigev_notify; /* Notification method */
		int          sigev_signo;  /* Notification signal */
		union sigval sigev_value;  /* Data passed with notification */
		void       (*sigev_notify_function) (union sigval);
						/* Function used for thread notification (SIGEV_THREAD) */
		void        *sigev_notify_attributes;
						/* Attributes for notification thread (SIGEV_THREAD) */
		pid_t        sigev_notify_thread_id;
						/* ID of thread to signal (SIGEV_THREAD_ID) */
	};

	void free(void *ptr);
	void *calloc(size_t nmemb, size_t size);
	typedef long int ssize_t;
	ssize_t read(int fd, void *buf, size_t count);

	enum
	{
	  SI_ASYNCNL = -60,
	  SI_TKILL = -6,
	  SI_SIGIO,
	  SI_ASYNCIO,
	  SI_MESGQ,
	  SI_TIMER,
	  SI_QUEUE,
	  SI_USER,
	  SI_KERNEL = 0x80
	};
	const char *gai_strerror(int errcode);
	struct gaicb {
	  const char *ar_name;
	  const char *ar_service;
	  const struct addrinfo *ar_request;
	  struct addrinfo *ar_result;
	  int __return;
	  int __unused[5];
	};
	int getaddrinfo_a(int mode, struct gaicb *list[], int nitems, struct sigevent *sevp);
	int gai_error(struct gaicb *req);
	int gai_cancel(struct gaicb *req);
]]

SIG_BLOCK       = 0 -- Block signals.
SIGUSR1         = 10
EAGAIN          = 11

GAI_WAIT        = 0
GAI_NOWAIT      = 1

EAI_BADFLAGS    = -1 -- Invalid value for `ai_flags' field.
EAI_NONAME      = -2 -- NAME or SERVICE is unknown.
EAI_AGAIN       = -3 -- Temporary failure in name resolution.
EAI_FAIL        = -4 -- Non-recoverable failure in name res.
EAI_FAMILY      = -6 -- `ai_family' not supported.
EAI_SOCKTYPE    = -7 -- `ai_socktype' not supported.
EAI_SERVICE     = -8 -- SERVICE not supported for `ai_socktype'.
EAI_MEMORY      = -10 -- Memory allocation failure.
EAI_SYSTEM      = -11 -- System error returned in `errno'.
EAI_OVERFLOW    = -12 -- Argument buffer overflow.
EAI_NODATA      = -5 -- No address associated with NAME.
EAI_ADDRFAMILY  = -9 -- Address family for NAME not supported.
EAI_INPROGRESS  = -100 -- Processing request in progress.
EAI_CANCELED    = -101 -- Request canceled.
EAI_NOTCANCELED = -102 -- Request not canceled.
EAI_ALLDONE     = -103 -- All requests done.
EAI_INTR        = -104 -- Interrupted by a signal.
EAI_IDN_ENCODE  = -105 -- IDN encoding failed.

NI_MAXSERV      = 32
NI_MAXHOST      = 1025

NI_NUMERICHOST  = 1
NI_NUMERICSERV  = 2
NI_NOFQDN       = 4
NI_NAMEREQD     = 8
NI_DGRAM        = 16


local function addrinfo_to_string ( sockaddr , addr_len )
	local host_len = NI_MAXHOST or 1025
	local host = ffi.new ( "char[?]" , host_len )
	local serv_len = NI_MAXSERV or 32
	local serv = ffi.new ( "char[?]" , serv_len )
	local flags = bit.bor ( NI_NUMERICHOST , NI_NUMERICSERV )
	local err = ffi.C.getnameinfo ( sockaddr , addr_len , host , host_len , serv , serv_len , flags )
	if err ~= 0 then
			error ( ffi.string ( ffi.C.gai_strerror ( err ) ) )
	end
	return ffi.string ( host ) , ffi.string ( serv )
end

local signum = ffi.C.__libc_current_sigrtmin()

local mask = ffi.new ( "sigset_t[1]" )
ffi.C.sigemptyset ( mask )
ffi.C.sigaddset ( mask, signum )
if ffi.C.sigprocmask ( SIG_BLOCK, mask, nil ) == -1 then
	error ( ffi.string ( ffi.C.strerror( ffi.errno() ) ) )
end

for i=1,1e3 do

local sfd = ffi.C.signalfd ( -1, mask, 0 )
if sfd == -1 then
	error ( ffi.string ( ffi.C.strerror( ffi.errno() ) ) )
end

local list = ffi.new ( "struct gaicb*[?]",n )
for j=1,n do
	local a = ffi.cast ( "struct gaicb*" , ffi.C.calloc ( 1 , ffi.sizeof("struct gaicb") ) )
	if a == ffi.NULL then error("No Memory") end
	a[0].ar_name = tquery[j]
	list[j-1] = a
end

local sigevent = ffi.new ( "struct sigevent" )
sigevent.sigev_notify          = ffi.C.SIGEV_SIGNAL
sigevent.sigev_signo           = signum
sigevent.sigev_value.sival_ptr = list

local r = anl.getaddrinfo_a ( GAI_NOWAIT, list , n , sigevent )
if r ~= 0 then
	error ( ffi.string ( ffi.C.strerror ( r ) ) )
end

local info  = ffi.new ( "struct signalfd_siginfo[1]" )

local r = ffi.C.read ( sfd , info, ffi.sizeof(info) )
if r == -1 then
	error ( ffi.string ( ffi.C.strerror ( ffi.errno() ) ) )
end
assert ( r == ffi.sizeof( info ) )
assert ( info[0].ssi_code == ffi.C.SI_ASYNCNL )
local list = ffi.cast ( "struct gaicb**" , info[0].ssi_ptr ) --t[ info[0].ssi_int ]
for j=1,n do
	local r = anl.gai_error( list[j-1] )
	if r ~= 0 then
		print(string.format("FAILURE: %30s: %s", ffi.string( list[j-1].ar_name ), ffi.string ( anl.gai_strerror(r) ) ) )
	else
		print(string.format("SUCCESS: %30s: %s %s", ffi.string ( list[j-1].ar_name ), addrinfo_to_string ( list[j-1].ar_result.ai_addr, list[j-1].ar_result.ai_addrlen ) ) )
	end
	ffi.C.free(list[j-1])
end

io.stdout:write("\n")
end

print("DONE")
local err = anl.gai_cancel(nil)
if err ~= EAI_ALLDONE then
	error ( anl.gai_strerror ( err ) )
end
print("And canceled")


Create a new paste based on this one


Comments: