Hi

I found a strange behaviour in `dlerror` with regard
to errno. When the function is called, it returns the
correct error message but sets errno to ENOSYS.

Thus, future usages of errno don't reflect the real reason
why the previous call to `dlopen` failed.

A little test case for this quirk is attached and can be compiled
with:
        LDFLAGS="-ldl" make main

The output it produces is the one listed below.

  1    shobj: (nil)
  2    dlerror: ./non-existent.so: cannot open shared object file: No such file 
or directory
  3    errno1: [40000002] No such file or directory
  4    errno2: [4000004e] Function not implemented

Line 1 shows `dlopen` actually failed, line 2 is the message returned
by `dlerror`, line 3 is `errno` between those functions and line 4 is
`errno` after `dlerror`.

This issue has two consequences for the console-client:

  1. It produces a misleading error message when a driver's shared
     library is not found.

  2. The drivers will only be looked for in the first directory
     specified by "driver path" because the error is no longer ENOENT.
     (lines 118-140 of console-client/driver.c)

Having a look at glibc source, dlerror.c file, there's nothing that
could be labeled as unimplemented, at a first glance; just calls to
things like asprintf, strcmp and free.

Any ideas?

Regards,
Diego

--

P.S. I stumbled upon this issue by following the advice in
/etc/defaults/hurd-console of setting KBD to "-d xkb".
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char** argv)
{
  char* dlerror_msg;
  int errno1, errno2;

  void* shobj = dlopen ("./non-existent.so", RTLD_LAZY);

  errno1 = errno;
  dlerror_msg = dlerror () ?: "[no error]";
  errno2 = errno;

  printf ("shobj: %p\n", shobj);
  printf ("dlerror: %s\n", dlerror_msg);
  printf ("errno1: [%x] %s\n", errno1, strerror (errno1));
  printf ("errno2: [%x] %s\n", errno2, strerror (errno2));

  return 0;
}

Reply via email to