Page MenuHome GnuPG

estream: Use destructor instead of atexit for gpgrt cleanup
Needs ReviewPublic

Authored by calvin on Oct 4 2024, 4:40 PM.

Details

Reviewers
None
Group Reviewers
gpgrt
Summary

atexit handlers are impossible to remove on most platforms (except AIX
for some reason), and isn't symmetrical with when we initialize things.
Since we initialize things with a constructor, we should be using a
destructor instead of registering an atexit handler.

While applications shouldn't dlclose libgpg-error, they might do it
unintentionally, and this should be handled to avoid surprises when our
atexit handler disappears into the void.

In particular at least, this causes problems with applications that
dlclose things that depend on liggpg-error. For instance, PHP will
dlclose extensions, and if any depend on libgpg-error, these will also
get closed as part of removing unused dependents.

T1749 tried to deal with this by not using atexit, but this had the
effect of not doing deinit work. This moves deinit work into the dtor,
and sets up gpgrt for the concept of destructors anyways.

Test Plan
  • Build libgpg-error on a platform that clobbers unloaded libraries consistently on dlclose, i.e. NetBSD or AIX
  • Build something that consumes libgpg-error or a dependency and dlcloses that (i.e. the PHP gnupg extension) i.e. sample program
#include <stdio.h>
#include <dlfcn.h>
#include <gpgme.h>

int main(int argc, char **argv)
{
        void *gpgme_dl = dlopen("/QOpenSys/pkgs/lib/libgpgme.so.11(shr_64.o)", RTLD_MEMBER | RTLD_NOW | RTLD_GLOBAL);
        if (gpgme_dl == NULL) {
                fputs("ope load", stderr);
        }
        const char*(*func)(const char*) = dlsym(gpgme_dl, "gpgme_get_dirinfo");
        if (func == NULL) {
                fputs("ope func", stderr);
        }
        printf("! %s\n", func("homedir"));
        dlclose(gpgme_dl);
        return 0;
}
  • Ensure that it does not segfault on exit (before this, atexit handler would get clobbered in memory by dlclose, now instead gets called upon dlclose or exit)

Diff Detail

Repository
rE libgpg-error
Lint
Lint Skipped
Unit
Unit Tests Skipped