Destructoid just posted:

All Path of Exile 2 Last of the Druids Twitch drops and how to get them

Patch 0.4 patch, aka Last of the Druids update in Path of Exile 2, is not live, and a fresh Twitch drops campaign is now live. The latest campaign has four unique rewards for the players to obtain for free. To do so, they will need to complete specific tasks while the campaign is live. This guide will provide you with all the required information ...

destructoid.com/all-path-of-ex…

#gamingNews

Venezuela oil exports fall steeply after US forces seize tanker off coast aljazeera.com/news/2025/12/13/…

“We know how much God loves us, and we have put our trust in his love. God is love, and all who live in love live in God, and God lives in them.”
1 John 4:16 (NLT)

bible.com/bible/compare/1JN.4.…
#Bible #VerseOfTheDay

Ensuring a National Policy Framework for Artificial Intelligence

Link: whitehouse.gov/presidential-ac…
Discussion: news.ycombinator.com/item?id=4…

Show HN: Tiny VM sandbox in C with apps in Rust, C and Zig

Link: github.com/ringtailsoftware/uv…
Discussion: news.ycombinator.com/item?id=4…

Apple has locked my Apple ID, and I have no recourse. A plea for help

Link: hey.paris/posts/appleid/
Discussion: news.ycombinator.com/item?id=4…

#apple

Gamespot just posted:

Exclusive Halloween 4K Steelbooks And Box Sets On Sale For Lowest Prices Yet

Halloween (1978): Limited Edition Steelbook (4K) $39.49 (was $45) See at Amazon Halloween II (1981): Limited Edition Steelbook (4K) $37 (was $45) See at Amazon Halloween III: Season of the Witch (1982): Limited Edition Steelbook (4K) $40 (was $45) See at Amazon Amazon's weekly catalog of movie and TV ...

gamespot.com/articles/hallowee…

#gamingNews

DSOGaming just posted:

Borderlands 4 Gets a Major Performance Update on PC

As I wrote in my PC Performance Analysis a few months ago, Borderlands 4 had serious performance problems when it launched on PC. The game was poorly optimized and had many technical issues. Now, in December 2025, a big new PC update has been released, and it promises to fix many of those problems. Going …

dsogaming.com/patches/borderla…

#gamingNews

愛希れいかが4つのメイクで“至上の美”、2026-2027年カレンダー「Elysia」発売(ステージナタリー)
news.yahoo.co.jp/articles/2e02…
#news_yahoo_media_natalies

Venezuela Condemns US Theft of Oil Tanker as Act of Piracy (+International Reactions) orinocotribune.com/venezuela-c…

Palestinians in Gaza are dying as the Israeli siege turns harsh winter weather deadly #Palestine mondoweiss.net/2025/12/palesti…

LIVESTREAM: Independent Media Alliance – Christmas Q&A off-guardian.org/2025/12/12/li…

Nintendo Life just posted:

Kirby Air Riders Dev Team Disbanding Soon, Game Updates Also Ending

It was fun while it lasted.Yesterday, Kirby Air Riders got a major update, bumping the Switch 2 exclusive up to Version 1.2.0. It turns out this might be one of the final significant patches.According to a roughly translated post on social media, the game's director Masahiro Sakurai said the Kirby Air Riders development team will be disbanding in the near ...

nintendolife.com/news/2025/12/…

#gamingNews

Cambodia claims Thailand still bombing hours after Trump ceasefire call aljazeera.com/news/2025/12/13/…

12 dead and 27,000 tents destroyed in Gaza storms; Report finds $1 billion in revenue from Gaza aid extortion; Trump signs order blocking state laws on AI dropsitenews.com/p/twelve-dead…

Saudi Arabia and the UAE: Two rival allies. #shorts #podcast #uae #saudiarabia

Saudi Arabia and the UAE: Two rival allies. #shorts #podcast #uae #saudiarabia

World News in Brief: December 12 en.nhandan.vn/world-news-in-br…

ミュージカル「ダディ・ロング・レッグズ」井上芳雄が体調不良で休演、代役は佐野眞介(ステージナタリー)
news.yahoo.co.jp/articles/65ab…
#news_yahoo_media_natalies

HOHOHO!「クリスマス・ワンダーランド」が開幕、アンバサダー増田貴久は「体感15分」(ステージナタリー)
news.yahoo.co.jp/articles/5668…
#news_yahoo_media_natalies

Freezing temperatures and floods kill infants and children in storm-battered Gaza tehrantimes.com/news/521520/Fr…

結構いい感じです、ザジ・ズーの1年ぶり本公演「ザジ・ズー現代贋作劇場」本日スタート(ステージナタリー)
news.yahoo.co.jp/articles/f6e0…
#news_yahoo_media_natalies

‘Release Gaza footage,’ British victim demands in new spy flight documentary declassifieduk.org/release-gaz…

Async DNS

Link: flak.tedunangst.com/post/async…
Discussion: news.ycombinator.com/item?id=4…


async dns


curl experimented with using pthread_cancel to timeout async DNS requests and it blew up. What else can we do?

Out of curiosity, I decided to review some alternatives and see how they work. My personal priorities are control over events; no background threads or signals or secret mechanisms.

getaddrinfo


The tried and true classic technique is to call getaddrinfo in a thread. Probably with more than one thread so you don’t get stuck behind a single slow request, but probably not boundless either. You can also use a separate process if you don’t use threads.

This is probably good enough for many uses.

getaddrinfo_a


glibc provides getaddrinfo_a which basically does the thread dance for you. Some of it. It comes with some caveats, and it’s distinctly non portable, and probably doesn’t mesh with your idea of an event loop. Passing.

c-ares


c-ares is a standalone DNS library. It supports async queries via a threaded backend or an event driven system. I think the thread backend has the same issues, in that it uses a callback and then you need to push the results back into your application.

Alas, the event system uses lots of callbacks as well. This also includes some dire warnings in the documentation. “When the associated callback is called, it is called with a channel lock so care must be taken to ensure any processing is minimal to prevent DNS channel stalls.” Everyone knows the ideal callback just sets a flag, etc., but also everyone is inevitably tempted to do just one more thing, and hey look, it works fine, wait, why did it break. And thus I have a strong preference for library interfaces where you call into it, get some results, but any time you’re in your own code, you’re free to do what you want.

But worth a try. Based on the sample code I wrote the quickest dirtiest demo I could.

c-ares code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <arpa/inet.h>

#include <ares.h>

struct server {
    char name[32];
    char ip[16];
    int status;
};

struct everything {
    struct server servers[1];
    int nservers;
    struct pollfd pfds[4];
    int npfds;
};

static void
addrinfo_cb(void *arg, int status, int timeouts, struct ares_addrinfo *result)
{
    struct server *server = arg;
    server->status = 3;
    if (!result)
        return;
    for (struct ares_addrinfo_node *node = result->nodes; node != NULL; node = node->ai_next) {
        if (node->ai_family == AF_INET) {
            struct sockaddr_in *in_addr = (void *)node->ai_addr;
            inet_ntop(node->ai_family, &in_addr->sin_addr, server->ip, sizeof(server->ip));        }
    }
}

static void
socket_cb(void *arg, ares_socket_t fd, int readable, int writable)
{
    struct everything *state = arg;
    printf("socket: %d r/w: %d %d\n", fd, readable, writable);

    int idx = -1;
    for (int i = 0; i < 4; i++) {
        if (state->pfds[i].fd == fd) {
            idx = i;
            break;
        }
    }
    if (idx == -1) {
        for (int i = 0; i < 4; i++) {
            if (state->pfds[i].fd == -1) {
                idx = i;
                state->pfds[idx].fd = fd;
                state->npfds++;
                break;
            }
        }
    }
    if (idx == -1)
        abort();

    if (!readable && !writable) {
        state->pfds[idx].fd = -1;
        state->npfds--;
        return;
    }
    state->pfds[idx].fd = fd;
    state->pfds[idx].events = 0;
    if (readable)
        state->pfds[idx].events |= POLLIN;
    if (writable)
        state->pfds[idx].events |= POLLOUT;
}

int
main(int argc, char **argv)
{
    struct everything state;
    memset(&state, 0, sizeof(state));
    strlcpy(state.servers[0].name, argv[1], sizeof(state.servers[0].name));
    state.servers[0].status = 1;
    state.nservers = 1;
    for (int i = 0; i < 4; i++)
        state.pfds[i].fd = -1;

    ares_library_init(ARES_LIB_INIT_ALL);

    struct ares_options options;
    memset(&options, 0, sizeof(options));
    int optmask = 0;
    options.flags = ARES_FLAG_EDNS | ARES_FLAG_DNS0x20;
    optmask |= ARES_OPT_FLAGS;
    options.sock_state_cb = socket_cb;
    options.sock_state_cb_data = &state;
    optmask |= ARES_OPT_SOCK_STATE_CB;

    ares_channel_t *channel;
    ares_init_options(&channel, &options, optmask);

    ares_fd_events_t ares_fds[1];

    while (1) {
        printf("top of loop\n");
        for (int i = 0; i < state.nservers; i++) {
            printf("processing server %d\n", i);
            struct server *server = &state.servers[i];
            switch (server->status) {
            case 1:
                {
                    struct ares_addrinfo_hints hints;
                    memset(&hints, 0, sizeof(hints));
                    hints.ai_family = AF_UNSPEC;
                    hints.ai_flags  = ARES_AI_CANONNAME;
                    ares_getaddrinfo(channel, argv[1], NULL, &hints, addrinfo_cb, server);
                    server->status = 2;
                }
                break;
            case 2:
                printf("woke up while working\n");
                break;
            case 3:
                printf("got it, done: %s -> %s\n", server->name, server->ip);
                return 0;
            }
        }
        if (state.npfds == 0) {
            printf("confused. nothing to poll\n");
            return 1;
        }
        int res = poll(state.pfds, 4 /* state.npfds */, 2000);
        printf("poll results: %d\n", res);
        if (res > 0) {
            ares_fd_events_t events[4];
            int nevents = 0;
            for (int i = 0; i < 4 /* state.npfds */; i++) {
                if (!state.pfds[i].revents)
                    continue;
                events[nevents].fd = state.pfds[i].fd;
                events[nevents].events = 0;
                if (state.pfds[i].revents & (POLLERR|POLLHUP|POLLIN))
                    events[nevents].events |= ARES_FD_EVENT_READ;
                if (state.pfds[i].revents & (POLLOUT))
                    events[nevents].events |= ARES_FD_EVENT_WRITE;
                nevents++;
            }
            ares_process_fds(channel, events, nevents, 0);
        }
    }
}

It’s okay, but the callbacks are annoying. Notifying me which descriptors need watching means I’m required to pack up my poll structure so I can access it in the callbacks, etc. Everything gets bound just a little bit tighter.

wadns


Among the alternatives the c-ares project helpfully lists, is dns.c. This sounds enticing.

On the downside, it’s not clear where the demo code stops and the functional code begins. As in, there’s a getaddrinfo sample, but it incorporates a lot of other code that doesn’t seem to be public. The public header doesn’t actually expose a means to interface with an event loop. The code is meant to be integrated into a project, which is understandable and even advantageous, but it means no demo today.

asr


The asr code was written for smtpd in OpenBSD. It doesn’t use threads and requires the caller to push events. Unfortunately, a portable version currently only exists in the OpenSMTPD repo. On the plus side, it’s used as the basis for the libc resolver in OpenBSD, which means the “sample” code to replace getaddrinfo literally is getaddrinfo.c.

I rewrote the c-ares demo to use asr. It comes out quite a bit shorter, and I think clearer as well.

asr code

<span class=bi>#include <sys/types.h></span>
<span class=bi>#include <sys/socket.h></span>
<span class=bi>#include <stdio.h></span>
<span class=bi>#include <stdlib.h></span>
<span class=bi>#include <string.h></span>
<span class=bi>#include <poll.h></span>
<span class=bi>#include <netdb.h></span>
<span class=bi>#include <asr.h></span>
<span class=bi>#include <arpa/inet.h></span>

<span class=tp>struct</span> server <span class=st>{</span>
    <span class=tp>char</span> name<span class=kw>[</span><span class=nm>32</span><span class=kw>]</span>;
    <span class=tp>char</span> ip<span class=kw>[</span><span class=nm>16</span><span class=kw>]</span>;
    <span class=tp>int</span> status;
    <span class=tp>struct</span> asr_query <span class=op>*</span>aq;
    <span class=tp>int</span> ar_fd;
<span class=st>}</span>;

<span class=tp>int</span>
main<span class=st>(</span><span class=tp>int</span> argc<span class=op>,</span> <span class=tp>char</span> <span class=op>**</span>argv<span class=st>)</span>
<span class=st>{</span>
    <span class=tp>struct</span> server servers<span class=kw>[</span><span class=nm>1</span><span class=kw>]</span> <span class=op>=</span> <span class=kw>{</span><span class=kw>}</span>;
    strlcpy<span class=kw>(</span>servers<span class=cm>[</span><span class=nm>0</span><span class=cm>]</span><span class=op>.</span>name<span class=op>,</span> argv<span class=cm>[</span><span class=nm>1</span><span class=cm>]</span><span class=op>,</span> sizeof<span class=cm>(</span>servers<span class=bi>[</span><span class=nm>0</span><span class=bi>]</span><span class=op>.</span>name<span class=cm>)</span><span class=kw>)</span>;
    servers<span class=kw>[</span><span class=nm>0</span><span class=kw>]</span><span class=op>.</span>status <span class=op>=</span> <span class=nm>1</span>;
    <span class=tp>int</span> nservers <span class=op>=</span> <span class=nm>1</span>;

    <span class=kw>while</span> <span class=kw>(</span><span class=nm>1</span><span class=kw>)</span> <span class=kw>{</span>
        <span class=tp>struct</span> pollfd pfds<span class=cm>[</span><span class=nm>4</span><span class=cm>]</span>;
        <span class=tp>int</span> npfds <span class=op>=</span> <span class=nm>0</span>;
        printf<span class=cm>(</span><span class=st>"top of loop\n"</span><span class=cm>)</span>;
        <span class=kw>for</span> <span class=cm>(</span><span class=tp>int</span> i <span class=op>=</span> <span class=nm>0</span>; i <span class=op><</span> nservers; i<span class=op>++</span><span class=cm>)</span> <span class=cm>{</span>
            printf<span class=bi>(</span><span class=st>"processing server %d\n"</span><span class=op>,</span> i<span class=bi>)</span>;
            <span class=tp>struct</span> server <span class=op>*</span>server <span class=op>=</span> &servers<span class=bi>[</span>i<span class=bi>]</span>;
            <span class=kw>switch</span> <span class=bi>(</span>server<span class=op>-></span>status<span class=bi>)</span> <span class=bi>{</span>
            <span class=kw>case</span> <span class=nm>1</span><span class=op>:</span>
                <span class=st>{</span>
                    <span class=tp>struct</span> addrinfo hints;
                    memset<span class=kw>(</span>&hints<span class=op>,</span> <span class=nm>0</span><span class=op>,</span> sizeof<span class=cm>(</span>hints<span class=cm>)</span><span class=kw>)</span>;
                    hints<span class=op>.</span>ai_family <span class=op>=</span> AF_UNSPEC;
                    hints<span class=op>.</span>ai_socktype <span class=op>=</span> SOCK_STREAM;
                    server<span class=op>-></span>aq <span class=op>=</span> getaddrinfo_async<span class=kw>(</span>server<span class=op>-></span>name<span class=op>,</span> <span class=st>"80"</span><span class=op>,</span> &hints<span class=op>,</span> <span class=bi>NULL</span><span class=kw>)</span>;
                    server<span class=op>-></span>status <span class=op>=</span> <span class=nm>2</span>;
                <span class=st>}</span>
                <span class=cm>// fallthrough</span>
          <span class=kw>case</span> <span class=nm>2</span><span class=op>:</span>
                <span class=st>{</span>
                    printf<span class=kw>(</span><span class=st>"ready to run\n"</span><span class=kw>)</span>;
                    <span class=tp>struct</span> asr_result ar;
                    <span class=tp>int</span> rv <span class=op>=</span> asr_run<span class=kw>(</span>server<span class=op>-></span>aq<span class=op>,</span> &ar<span class=kw>)</span>;
                    <span class=kw>switch</span> <span class=kw>(</span>rv<span class=kw>)</span> <span class=kw>{</span>
                    <span class=kw>case</span> <span class=nm>0</span><span class=op>:</span>
                        pfds<span class=cm>[</span>npfds<span class=cm>]</span><span class=op>.</span>fd <span class=op>=</span> ar<span class=op>.</span>ar_fd;
                        pfds<span class=cm>[</span>npfds<span class=cm>]</span><span class=op>.</span>events <span class=op>=</span> <span class=nm>0</span>;
                        <span class=kw>if</span> <span class=cm>(</span>ar<span class=op>.</span>ar_cond <span class=op>==</span> ASR_WANT_READ<span class=cm>)</span>
                            pfds<span class=cm>[</span>npfds<span class=cm>]</span><span class=op>.</span>events <span class=op>=</span> POLLIN;
                        <span class=kw>else</span>
                            pfds<span class=cm>[</span>npfds<span class=cm>]</span><span class=op>.</span>events <span class=op>=</span> POLLOUT;
                        npfds<span class=op>++</span>;
                        server<span class=op>-></span>ar_fd <span class=op>=</span> ar<span class=op>.</span>ar_fd;
                        server<span class=op>-></span>status <span class=op>=</span> <span class=nm>3</span>;
                        <span class=kw>break</span>;
                    <span class=kw>case</span> <span class=nm>1</span><span class=op>:</span>
                        <span class=cm>{</span>
                            <span class=tp>struct</span> addrinfo <span class=op>*</span>res;
                            <span class=kw>for</span> <span class=bi>(</span>res <span class=op>=</span> ar<span class=op>.</span>ar_addrinfo; res; res <span class=op>=</span> res<span class=op>-></span>ai_next<span class=bi>)</span> <span class=bi>{</span>
                                <span class=kw>if</span> <span class=st>(</span>res<span class=op>-></span>ai_family <span class=op>==</span> AF_INET<span class=st>)</span> <span class=st>{</span>
                                    <span class=tp>struct</span> sockaddr_in <span class=op>*</span>in_addr <span class=op>=</span> <span class=kw>(</span><span class=tp>void</span> <span class=op>*</span><span class=kw>)</span>res<span class=op>-></span>ai_addr;
                                    inet_ntop<span class=kw>(</span>res<span class=op>-></span>ai_family<span class=op>,</span> &in_addr<span class=op>-></span>sin_addr<span class=op>,</span> server<span class=op>-></span>ip<span class=op>,</span> sizeof<span class=cm>(</span>server<span class=op>-></span>ip<span class=cm>)</span><span class=kw>)</span>;
                                <span class=st>}</span>
                            <span class=bi>}</span>
                            server<span class=op>-></span>status <span class=op>=</span> <span class=nm>4</span>;
                        <span class=cm>}</span>
                        <span class=kw>break</span>;
                    <span class=kw>}</span>
                <span class=st>}</span>
                <span class=kw>break</span>;
            <span class=kw>case</span> <span class=nm>3</span><span class=op>:</span>
                printf<span class=st>(</span><span class=st>"woke up while working\n"</span><span class=st>)</span>;
                <span class=kw>break</span>;
            <span class=kw>case</span> <span class=nm>4</span><span class=op>:</span>
                printf<span class=st>(</span><span class=st>"got it, done: %s -> %s\n"</span><span class=op>,</span> server<span class=op>-></span>name<span class=op>,</span> server<span class=op>-></span>ip<span class=st>)</span>;
                <span class=kw>return</span> <span class=nm>0</span>;
            <span class=bi>}</span>
        <span class=cm>}</span>
        <span class=kw>if</span> <span class=cm>(</span>npfds <span class=op>==</span> <span class=nm>0</span><span class=cm>)</span>
            <span class=kw>continue</span>;
        <span class=tp>int</span> res <span class=op>=</span> poll<span class=cm>(</span>pfds<span class=op>,</span> npfds<span class=op>,</span> <span class=nm>2000</span><span class=cm>)</span>;
        printf<span class=cm>(</span><span class=st>"poll results: %d\n"</span><span class=op>,</span> res<span class=cm>)</span>;
        <span class=kw>if</span> <span class=cm>(</span>res <span class=op>></span> <span class=nm>0</span><span class=cm>)</span> <span class=cm>{</span>
            <span class=kw>for</span> <span class=bi>(</span><span class=tp>int</span> i <span class=op>=</span> <span class=nm>0</span>; i <span class=op><</span> npfds; i<span class=op>++</span><span class=bi>)</span> <span class=bi>{</span>
                <span class=kw>if</span> <span class=st>(</span><span class=op>!</span>pfds<span class=kw>[</span>i<span class=kw>]</span><span class=op>.</span>revents<span class=st>)</span>
                    <span class=kw>continue</span>;
                <span class=kw>for</span> <span class=st>(</span><span class=tp>int</span> j <span class=op>=</span> <span class=nm>0</span>; j <span class=op><</span> nservers; j<span class=op>++</span><span class=st>)</span> <span class=st>{</span>
                    <span class=kw>if</span> <span class=kw>(</span>pfds<span class=cm>[</span>i<span class=cm>]</span><span class=op>.</span>fd <span class=op>==</span> servers<span class=cm>[</span>j<span class=cm>]</span><span class=op>.</span>ar_fd<span class=kw>)</span>
                        servers<span class=kw>[</span>j<span class=kw>]</span><span class=op>.</span>status <span class=op>=</span> <span class=nm>2</span>;
                <span class=st>}</span>
            <span class=bi>}</span>
        <span class=cm>}</span>
    <span class=kw>}</span>
<span class=st>}</span>

I like this API. It’s very much like read or write in that it either gives you an answer, or tells you to come back later, and then it’s up to you to decide when that is.


What is Socialism with Chinese Characteristics? This is how China's economic model works

What is Socialism with Chinese Characteristics? This is how China's economic model works

Rear Admiral Sayyari: Army stands firm against any enemy infiltration into Iran parstoday.ir/en/news/iran-i240…

真琴つばさ、Xmas LIVE「Christmassy★」で芸能生活40周年の2025年を締めくくり(ステージナタリー)
news.yahoo.co.jp/articles/d0ef…
#news_yahoo_media_natalies

Fedora: Open-source repository for long-term digital preservation

Link: fedorarepository.org/
Discussion: news.ycombinator.com/item?id=4…

OpenAI are quietly adopting skills, now available in ChatGPT and Codex CLI

Link: simonwillison.net/2025/Dec/12/…
Discussion: news.ycombinator.com/item?id=4…

China to work with ASEAN to align development strategies, resist unilateral bullying: Chinese FM china.org.cn/2025-12/12/conten…

Using secondary school maths to demystify AI

Link: raspberrypi.org/blog/secondary…
Discussion: news.ycombinator.com/item?id=4…

Gamespot just posted:

Pragmata Preorders Are Already Discounted On PC

Pragmata $60 | Releases April 24, 2026 Preorder at Amazon Pragmata (PC) Save 17% on the PC version Pragmata Standard Edition Pragmata Digital Deluxe Edition Capcom has a busy 2026 in store, with numerous big video game releases already slated for the year. But while many of those upcoming titles are from established franchises like Resident Evil ...

gamespot.com/articles/pragmata…

#gamingNews

劇団親知らズ、2チーム上演の「眠レ、巴里」が開幕 竹内銃一郎が描くとある姉妹の物語(ステージナタリー)
news.yahoo.co.jp/articles/b770…
#news_yahoo_media_natalies

The Empire Is Scrambling To Fully Dominate Latin America, And Other Notes thealtworld.substack.com/p/the…

Ensuring a National Policy Framework for Artificial Intelligence

Link: whitehouse.gov/presidential-ac…
Discussion: news.ycombinator.com/item?id=4…

つかこうへい十七回忌特別公演「熱海殺人事件」に荒井敦史・大原優乃・村山彩希ら(ステージナタリー)
news.yahoo.co.jp/articles/bb79…
#news_yahoo_media_natalies

Venezuela files complaint with the International Maritime Organization regarding U.S. attack on an oil tanker radiohc.cu/en/venezuela-files-…