make dlerror conform to posix
authorRich Felker <dalias@aerifal.cx>
Fri, 23 Mar 2012 04:28:20 +0000 (00:28 -0400)
committerRich Felker <dalias@aerifal.cx>
Fri, 23 Mar 2012 04:28:20 +0000 (00:28 -0400)
the error status is required to be sticky after failure of dlopen or
dlsym until cleared by dlerror. applications and especially libraries
should never rely on this since it is not thread-safe and subject to
race conditions, but glib does anyway.

src/ldso/dynlink.c

index 6ff8850..e0013ec 100644 (file)
@@ -1,4 +1,3 @@
-#ifdef __PIC__
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <dlfcn.h>
 
+static int errflag;
+
+#ifdef __PIC__
+
 #include "reloc.h"
 
 #if ULONG_MAX == 0xffffffff
@@ -631,12 +634,13 @@ void *dlopen(const char *file, int mode)
                tail = orig_tail;
                tail->next = 0;
                p = 0;
+       } else p = load_library(file);
+
+       if (!p) {
+               errflag = 1;
                goto end;
        }
 
-       p = load_library(file);
-       if (!p) goto end;
-
        /* First load handling */
        if (!p->deps) {
                load_deps(p);
@@ -674,8 +678,11 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra)
                if (!p) p=head;
                p=p->next;
        }
-       if (p == head || p == RTLD_DEFAULT)
-               return find_sym(head, s, 0);
+       if (p == head || p == RTLD_DEFAULT) {
+               void *res = find_sym(head, s, 0);
+               if (!res) errflag = 1;
+               return res;
+       }
        h = hash(s);
        sym = lookup(s, h, p->syms, p->hashtab, p->strings);
        if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
@@ -686,6 +693,7 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra)
                if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
                        return p->deps[i]->base + sym->st_value;
        }
+       errflag = 1;
        return 0;
 }
 
@@ -710,6 +718,8 @@ void *__dlsym(void *p, const char *s, void *ra)
 
 char *dlerror()
 {
+       if (!errflag) return 0;
+       errflag = 0;
        return "unknown error";
 }