xerces-c 库函数 returns NULL when daemon 运行 via inetd
xerces-c library function returns NULL when daemon ran via inetd
我的应用程序是一个服务器应用程序,它接受来自用户的一些预定义命令并显示从服务器端存在的 XML 个文件中获取的相应输出。
为了解析 XML 文件,我使用的是来自 apache 的 xerces-c 库版本 3.1.2。当在终端上手动 运行 时,该应用程序工作正常。
但我想通过网络上的 telnet 运行 应用程序,这样我就可以通过 telnet 向应用程序提供输入并在远程系统上接收输出。为此,我使用了 inetd 超级服务器并在 inetd.conf:
中添加了以下行
vterm stream tcp nowait root /path/to/my/binary/vterm vterm
然后在 /etc/services 中添加以下行以使其侦听端口 5000
vterm 5000/tcp
之后,当我尝试连接到我的应用程序时,我常常收到以下消息:
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.
当上面的连接关闭消息出现时,我以为我没有正确配置我的应用程序和 inetd。所以,我用一个没有使用任何额外库的简单二进制文件替换了我的二进制文件。只是简单的 cin 和 cout,效果非常好。
后来发现我的应用程序出了点问题,所以为此我使用了大量的 cout 来确定实际发生了什么。有了这个,我发现其中一个 xerces-c XML 解析库函数正在返回 NULL 并且使用这个 NULL 引用我试图在下面的行中调用一个函数,它使我的应用程序一启动就转储。
但问题是,当我 运行 在终端上手动我的应用程序时,同样的功能工作正常。完整的应用程序有点大,所以我创建了一个重现问题的演示代码。这是我的代码:
#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;
}
上面的代码在编译和手动 运行 时不会进入 "Doc is NULL" 的 if 条件并成功打印根元素标签名称,但是当我 运行 这个应用程序时在 inetd 后面,当我远程登录到它时,我能够看到 "Doc is NULL" 语句,并且在相同的消息 "Connection closed by foreign host." 之后,我的应用程序可能会被转储。
我现在有点疯了,因为我不确定到底要看哪里。当 运行 手动而不是通过 inetd 时,相同的代码可以工作。
所以,我在想我们在通过使用共享库的 inetd 执行进程时是否需要特别注意,就像这里我使用 xerces-c 共享库进行 XML 解析。
或者我的理解或我的代码还有什么可能有问题。
为什么相同的库函数在手动应用 运行 时工作得很好,而在通过 inetd 运行 时不工作?
我尝试使用 xinetd 而不是 inetd,但结果相同。
正如您自己所证明的,当您通过 inetd
启动您的工具时,工作目录是 /
。但是您的 XML 文件不在系统的根目录中。您可以将完整路径硬连接到您的应用程序中。更好的解决方案是将文件的位置作为参数传递。
我的应用程序是一个服务器应用程序,它接受来自用户的一些预定义命令并显示从服务器端存在的 XML 个文件中获取的相应输出。
为了解析 XML 文件,我使用的是来自 apache 的 xerces-c 库版本 3.1.2。当在终端上手动 运行 时,该应用程序工作正常。
但我想通过网络上的 telnet 运行 应用程序,这样我就可以通过 telnet 向应用程序提供输入并在远程系统上接收输出。为此,我使用了 inetd 超级服务器并在 inetd.conf:
中添加了以下行vterm stream tcp nowait root /path/to/my/binary/vterm vterm
然后在 /etc/services 中添加以下行以使其侦听端口 5000
vterm 5000/tcp
之后,当我尝试连接到我的应用程序时,我常常收到以下消息:
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.
当上面的连接关闭消息出现时,我以为我没有正确配置我的应用程序和 inetd。所以,我用一个没有使用任何额外库的简单二进制文件替换了我的二进制文件。只是简单的 cin 和 cout,效果非常好。
后来发现我的应用程序出了点问题,所以为此我使用了大量的 cout 来确定实际发生了什么。有了这个,我发现其中一个 xerces-c XML 解析库函数正在返回 NULL 并且使用这个 NULL 引用我试图在下面的行中调用一个函数,它使我的应用程序一启动就转储。
但问题是,当我 运行 在终端上手动我的应用程序时,同样的功能工作正常。完整的应用程序有点大,所以我创建了一个重现问题的演示代码。这是我的代码:
#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;
}
上面的代码在编译和手动 运行 时不会进入 "Doc is NULL" 的 if 条件并成功打印根元素标签名称,但是当我 运行 这个应用程序时在 inetd 后面,当我远程登录到它时,我能够看到 "Doc is NULL" 语句,并且在相同的消息 "Connection closed by foreign host." 之后,我的应用程序可能会被转储。
我现在有点疯了,因为我不确定到底要看哪里。当 运行 手动而不是通过 inetd 时,相同的代码可以工作。 所以,我在想我们在通过使用共享库的 inetd 执行进程时是否需要特别注意,就像这里我使用 xerces-c 共享库进行 XML 解析。 或者我的理解或我的代码还有什么可能有问题。 为什么相同的库函数在手动应用 运行 时工作得很好,而在通过 inetd 运行 时不工作?
我尝试使用 xinetd 而不是 inetd,但结果相同。
正如您自己所证明的,当您通过 inetd
启动您的工具时,工作目录是 /
。但是您的 XML 文件不在系统的根目录中。您可以将完整路径硬连接到您的应用程序中。更好的解决方案是将文件的位置作为参数传递。