Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can dlerror() return NULL if dlopen() fails?

I am working on system that loads all *.so modules library automatically by call a script.

I tried to update one of the modules to support XML-RPC. I used the library ibxmlrpc-c3-dev on Ubuntu 10.10. The problem that dlopen() fails after my changes and dlerror() returns NULL. The compilation does not return any error.

How can I debug and fix this issue? Below is the code:

#include "stdlib.h"
#include "stdio.h"
#ifndef WIN32
#include "unistd.h"
#endif

#include "xmlrpc-c/base.h"
#include "xmlrpc-c/server.h"
#include "xmlrpc-c/server_abyss.h"

#include "config.h"  /* information about this build environment */

And, I added this function , most of the lines are commented out ,even though dlopen() fails:

int RPC_Server(int           const port) {

   // xmlrpc_server_abyss_parms serverparm;
    //xmlrpc_registry * registryP;
    xmlrpc_env env;



    xmlrpc_env_init(&env);

    //registryP = xmlrpc_registry_new(&env);

   // xmlrpc_registry_add_method(
    //    &env, registryP, NULL, "sample.add", &sample_add, NULL);

    /* In the modern form of the Abyss API, we supply parameters in memory
       like a normal API.  We select the modern form by setting
       config_file_name to NULL:
    */
  //  serverparm.config_file_name = NULint
    RPC_Server(int           const port) {

       // xmlrpc_server_abyss_parms serverparm;
        //xmlrpc_registry * registryP;
        xmlrpc_env env;



        xmlrpc_env_init(&env);

        //registryP = xmlrpc_registry_new(&env);

       // xmlrpc_registry_add_method(
        //    &env, registryP, NULL, "sample.add", &sample_add, NULL);

        /* In the modern form of the Abyss API, we supply parameters in memory
           like a normal API.  We select the modern form by setting
           config_file_name to NULL:
        */
      //  serverparm.config_file_name = NULL;
       // serverparm.registryP        = registryP;
       // serverparm.port_number      = port;
       // serverparm.log_file_name    = "/tmp/xmlrpc_log";

       // printf("Running XML-RPC server...\n");

       // xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));

        /* xmlrpc_server_abyss() never returns */

        return 0;
    }L;
   // serverparm.registryP        = registryP;
   // serverparm.port_number      = port;
   // serverparm.log_file_name    = "/tmp/xmlrpc_log";

   // printf("Running XML-RPC server...\n");

   // xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));

    /* xmlrpc_server_abyss() never returns */

    return 0;
}

and this is the code the is used to load modules

#ifndef RTLD_NOW

#define RTLD_NOW DL_LAZY
#endif   
void* handle;
char* error;


handle=dlopen(mod->binary_file, RTLD_NOW); 

if (!handle){
LOG( " could not open file [%s]: %s\n",
    mod_cfg->binary_file, dlerror() );
return 0;
}
like image 797
Mike Albren Avatar asked Oct 29 '25 20:10

Mike Albren


1 Answers

In this code:

handle=dlopen(mod->binary_file, RTLD_NOW); 

if (!handle) {
    LOG( " could not open file [%s]: %s\n",
         mod_cfg->binary_file, dlerror() );

the most likely way I can think of for the dlerror() to return NULL here is if LOG itself calls one of the dl* routines (which would clear the error state that dlerror returns).

So,

  • show us what LOG macro (if indeed it is a macro) expands to, and
  • run the program under GDB, set breakpoints on dlopen, dlmopen, dlsym and dlvsym, and observe that one of them is called after your call to dlopen above and before your call to dlerror.
like image 73
Employed Russian Avatar answered Nov 01 '25 11:11

Employed Russian