Hello!

New example with __cxa_atexit works for me.

Let me summarize things:

Problem: any program using new Mesa from (xsrc/external/mit/MesaLib/dist/src/mesa/main/context.c r1.9), including NetBSD 11.0_BETA will crash on exit, because Mesa now calls atexit(3) from dlopen(3) DSO that is not supported in NetBSD. In base system this affects at least:

- glxinfo
- glxgears

And possibly some ports. Unfortunately I had not enough time to build any major browser (Firefox, Chromium) so can't confirm if these are also affected.

Possible solutions:

1. fix atexit(3) to work properly from DSOs (as done on most other systems)
2. use __attribute__((destructor))
3. use __cxa_atexit

So we have to decide what solution is best. Personally I think that this problem is blocker for 11.0_RELEASE. We can't ship system where major X programs just crash on exit.

Regards
  --Henryk Paluch


On 12/21/25 00:54, RVP wrote:
On Sat, 20 Dec 2025, RVP wrote:

Shared libs. should use __cxa_atexit() with a non-NULL `dso' parameter.


This works on FreeBSD, OpenBSD, Linux and even OpenIndiana. (Anything which
supports C++ would be my bet.)

-RVP

---START---
==> dl-atexit.c <==
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

static void
diemain(void)
{
     printf("%s: atexit handler\n", __func__);
}

int
main(void)
{
     extern const void* const __dso_handle;
     printf("__dso_handle = %p\n", __dso_handle);

     atexit(diemain);

     void *h = dlopen("libfoo.so", RTLD_LOCAL | RTLD_LAZY);
     if (h == NULL) {
         fprintf(stderr, "dlopen(): %s\n", dlerror());
         return 1;
     }
     void (*foo)(void) = dlsym(h, "foo");
     if (foo == NULL) {
         fprintf(stderr, "dlsym(foo): %s\n", dlerror());
         return 1;
     }
     printf("%s: calling foo()\n", __func__);
     foo();
     printf("%s: calling dlclose()\n", __func__);
     dlclose(h);
     printf("%s: exiting...\n", __func__);
     return 0;
}

==> libfoo.c <==
#include <stdio.h>
#include <stdlib.h>

extern int __cxa_atexit(void (*)(void*), void*, const void*);
extern const void* const __dso_handle;

static void
// die(void)
die(void* v)
{
     printf("%s: atexit handler\n", __func__);
}

void
foo(void)
{
     printf("__dso_handle = %p\n", __dso_handle);
     // atexit(die);
     __cxa_atexit(die, NULL, __dso_handle);
     printf("%s: atexit handler die() @ %p\n", __func__, die);
}

==> Makefile <==
LDFLAGS= -fuse-linker-plugin -Wl,--enable-new-dtags,-z,relro,-z,now

dl-atexit: dl-atexit.c libfoo.so
     cc -pie -fPIE -o dl-atexit dl-atexit.c -Wl,-rpath=$$(pwd) ${LDFLAGS}

libfoo.so: libfoo.c
     cc -shared -DPIC -fPIC -o libfoo.so libfoo.c ${LDFLAGS}

run: dl-atexit
     ./dl-atexit

clean:
     rm -f dl-atexit *.so *.core
---END---

Reply via email to