source: closures.c @ 1f65aee

Last change on this file since 1f65aee was 1f65aee, checked in by Benjamin Kaduk <kaduk@mit.edu>, 14 months ago
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.
  • Property mode set to 100644
File size: 928 bytes
Line 
1#define OWL_PERL
2#include "owl.h"
3#include <dlfcn.h>
4#include <gperl.h>
5#include <gperl_marshal.h>
6
7gboolean (*gvalue_from_sv) (GValue * value, SV * sv) = NULL;
8SV * (*sv_from_gvalue) (const GValue * value) = NULL;
9GClosure * (*perl_closure_new) (SV * callback, SV * data, gboolean swap) = NULL;
10
11/* Caller does not own return value */
12const char *owl_closure_init(void)
13{
14  void *handle = NULL;
15  const char *res = "Unable to dlopen self - huh?";
16
17  handle = dlopen(NULL, RTLD_LAZY | RTLD_NOLOAD);
18  if(handle) {
19    gvalue_from_sv = dlsym(handle, "gperl_value_from_sv");
20    sv_from_gvalue = dlsym(handle, "gperl_sv_from_value");
21    perl_closure_new = dlsym(handle, "gperl_closure_new");
22    /* ... */
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    }
31  }
32  return res;
33}
34
Note: See TracBrowser for help on using the repository browser.