Search code examples
c++xmllinuxxerces-cinetd

xerces-c library function returns NULL when daemon ran via inetd


My application is an server application that accepts some predefined commands from user and displays respective output that is taken from XML files present at the server end.

For parsing XML file I am using xerces-c library version 3.1.2 from apache. The application works fine when ran manually on a terminal.

But I wanted to run the application through telnet on a network so that I can give inputs to the application via telnet and receive output on a remote system too. For this I used inetd super server and added below line in inetd.conf:

vterm stream tcp nowait root /path/to/my/binary/vterm vterm

Then added below line in /etc/services to make it listen on port 5000

vterm 5000/tcp

After that when I tried to connect to my application I used to get below message:

msatyam@sabayon ~/programming/cpp/xml $ telnet localhost 5000
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

When the above connection closed message came I thought I have not configured properly my application with inetd. So, I replaced my binary with a simple binary which didn't used any extra libraries. Just simple cin's and cout's, which worked perfectly fine.

Then it turns out to be something wrong with my application so for this I put whole lot of cout's to identify what actually is happening. With this I found that one of the xerces-c XML parsing library function is returning NULL and with this NULL reference I am trying to call a function in line below which is making my application dump as soon as it starts.

But the thing is the same function is working fine when I run my application manually on a terminal. Full application is bit big so I have created a demo code which reproduces the problem. Here is my code:

    #include <xercesc/util/PlatformUtils.hpp>
    #include <xercesc/parsers/XercesDOMParser.hpp>
    #include <xercesc/dom/DOMDocument.hpp>
    #include <xercesc/dom/DOMElement.hpp>
    #include <iostream>

    using namespace std;
    using namespace xercesc;

int main()
{
    try
    {
        // init xerces XML Parser library
        XMLPlatformUtils::Initialize();
    }
    catch (const XMLException& ex)
    {
        cerr << ex.getMessage() << endl;
    }

    // parse a XML file
    XercesDOMParser* parser = new XercesDOMParser();
    try
    {
        parser->parse("sample.xml");
    }
    catch (const XMLException& ex)
    {
        cerr << ex.getMessage() << endl;
    }

    // get the document reference
    DOMDocument* doc = parser->getDocument();

    if (doc == NULL)
    {
        cout <<"Doc is NULL" << endl;
    }

    // else do stuff further
    // like get root element
    DOMElement* root = doc->getDocumentElement();

    // print node name
    string name = XMLString::transcode(root->getTagName());
    cout << "Name: " << name << endl;

    XMLPlatformUtils::Terminate();
return 0;
}

The above code when compiled and ran manually does not go into that if condition which says "Doc is NULL" and successfully prints the root element tag name, but when I run this application behind inetd and when I telnet to it I am able to see "Doc is NULL" statement and after that same message "Connection closed by foreign host." as my application would be probably dumping.

I am a bit out of brains now as I am not sure where to look exactly. As same code works when ran manually but not through inetd. So, I am thinking do we need to take some special attention while executing processes via inetd that uses shared libraries, like here I am using xerces-c shared library for XML parsing. Or What else could be possibly wrong with my understanding or my code. How come the same library functions works perfectly fine when application ran manually and not working when ran via inetd?

I tried the same using xinetd instead of inetd but same results.


Solution

  • As you have proven yourself, the working directory is / when you start your tool via inetd. But your XML file is not in the root directory of your system. You can hardwire the full path into your application. A better solution would be to pass the location of your file(s) as a parameter.