Skip to content

Commit

Permalink
Add async dns resolver for EPOLL, fix possible leak scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
etcimon committed Dec 13, 2023
1 parent 2232f72 commit a833f98
Show file tree
Hide file tree
Showing 9 changed files with 371 additions and 300 deletions.
25 changes: 22 additions & 3 deletions source/libasync/dns.d
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ private:
DNSCmdInfo m_cmdInfo;
StatusInfo m_status;
Thread m_owner;

static if (is_Windows || EPOLL) {
AsyncDNSRequest* m_activeReq;
}
public:
///
this(EventLoop evl) {
Expand Down Expand Up @@ -85,6 +87,7 @@ public:
m_cmdInfo.ipv6 = ipv6;
m_cmdInfo.url = cast(shared) url;
AsyncDNSRequest* dns_req = AsyncDNSRequest.alloc(this);
m_activeReq = cast(shared)dns_req;
return (cast(EventLoop)m_evLoop).resolve(dns_req, cmdInfo.url, 0, cmdInfo.ipv6?isIPv6.yes:isIPv6.no);
}
}
Expand Down Expand Up @@ -150,7 +153,13 @@ package:
}

synchronized void callback() {

static if (is_Windows || EPOLL) {
if (m_activeReq) {
import std.exception : assumeWontThrow;
assumeWontThrow(AsyncDNSRequest.free(cast(AsyncDNSRequest*)m_activeReq));
m_activeReq = null;
}
}
try {
m_handler(cast(NetworkAddress)m_cmdInfo.addr);
}
Expand All @@ -169,9 +178,19 @@ package struct AsyncDNSRequest
PADDRINFOEX infos;
}
static if (EPOLL) {
import libasync.internals.socket_compat : gaicb, sigevent;
import libasync.internals.socket_compat : gaicb, sigevent, addrinfo;
gaicb* host;
sigevent sig;
~this() {
static if (LOG) tracef("Destroying AsyncDNSRequest");
try {
ThreadMem.free(cast(addrinfo*)host.ar_request);
ThreadMem.free(cast(gaicb*)host);
} catch (Exception e) {
import libasync.internals.logging;
static if (LOG) tracef("Exception freeing in AsyncDNSRequest: %s", e.toString());
}
}
}
mixin FreeList!1_000;
}
Expand Down
8 changes: 2 additions & 6 deletions source/libasync/events.d
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ EventLoop getThreadEventLoop() nothrow {
return g_evLoop;
}

/*
static ~this() {
if (g_evLoop) g_evLoop.destroy();
}
*/

/// Event handlers can be registered to the event loop by being run(), all events
/// associated with them will trigger the OS to resume the underlying thread which
/// enables the existence of all the asynchroneous event objects in this library.
Expand All @@ -68,6 +62,8 @@ public:
/// and requires the process to be shut down for the resources to be collected automatically.
/// Used as a placeholder in the meantime.
void exit() {
if (this is g_evLoop)
g_evLoop = null;
m_evLoop.exit();
}

Expand Down
21 changes: 21 additions & 0 deletions source/libasync/internals/socket_compat.d
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,28 @@ else version (linux) {
EAI_INPROGRESS = -100,
EAI_SYSTEM = -10
}

extern(C) static union sigval_t { /* Data passed with notification */
int sival_int; /* Integer value */
void *sival_ptr; /* Pointer value */
}

extern(C) static struct sigevent_t {
int sigev_notify; /* Notification method */
int sigev_signo; /* Notification signal */
sigval_t sigev_value; /* Data passed with
notification */
void function(sigval_t) sigev_notify_function;
/* 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) */
}
extern(C) nothrow @nogc int getaddrinfo_a(int mode, gaicb **list, int nitems, sigevent *sevp);

}
extern (C) nothrow @nogc:

Expand Down
Loading

0 comments on commit a833f98

Please sign in to comment.