Changeset 1f65aee


Ignore:
Timestamp:
Aug 13, 2025, 4:53:31 PM (7 months ago)
Author:
Benjamin Kaduk <kaduk@mit.edu>
Branches:
master
Parents:
9a0d25d
git-author:
Benjamin Kaduk <kaduk@mit.edu> (08/13/25 16:52:28)
git-committer:
Benjamin Kaduk <kaduk@mit.edu> (08/13/25 16:53:31)
Message:
Properly check for dlsym() errors

In closures.c we dlopen() the main process address space so we can get
references to gvalue_from_sv, sv_from_gvalue, and perl_closure_new, but
we only check for errors by seeing if dlerror() returns a non-NULL
pointer (string).  This is not correct, since we are only supposed to
inspect dlerror()'s contents if one of a certain list of functions has
returned an error (dlerror() returns information about the latest such
error).

This causes problems on FreeBSD, where the NSS implementation in libc
performs a dlsym() lookup of a "_nss_cache_cycle_protection_function"
symbls, which fails in all processes other than nscd.  The FreeBSD libc
does not subsequently call dlerror() to clear the error string and so
it remains cached until we inspect it, and we erroneously treat this
cached value as indicating an error in our dlsym() usage, which trickles
up and becomes a fatal error at startup.

Fix the issue by only calling dlerror() if we experienced an error
return from dlsym() or dlclose(), clearing res to NULL in the success
case.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • closures.c

    r06e04a9 r1f65aee  
    2121    perl_closure_new = dlsym(handle, "gperl_closure_new");
    2222    /* ... */
    23     res = dlerror();
    24     dlclose(handle);
     23    if (dlclose(handle) != 0
     24        || gvalue_from_sv == NULL
     25        || sv_from_gvalue == NULL
     26        || perl_closure_new == NULL) {
     27            res = dlerror();
     28    } else {
     29      res = NULL;
     30    }
    2531  }
    2632  return res;
Note: See TracChangeset for help on using the changeset viewer.