我有一个程序,该程序使用Xerces XML framework读取RSS提要,并使用得到的信息“处理”。
该程序有效。
但是,如果通过Linux服务(以service myservice.sh start
开头的init.d脚本)以任何方式运行程序,则在读取某些亚洲供稿时,程序将抛出xercesc_3_2::TranscodingException
。
如果直接从init脚本或wrapper> myProgram或wrapper1> wrapper2> myProgram等调用该程序,则会引发异常。
我真的不知道为什么该程序无论是从命令行运行还是从init脚本运行都有不同的表现。
环境
Centos 6, 64-bit 4.4.211-1.el6.elrepo.x86_64
C++ '11
Xerces-C 3.2.1
这里是一个最小的测试用例。
XML测试文件:
<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF xml:lang="ja" xmlns="http://purl.org/rss/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" >
<item>
<title>「これまで採択した企画」を更新しました。</title>
<link>http://www.nhk.or.jp/kikakubosyuu/koremade.html?=20200430T1200</link>
<dc:date>2020-04-30T17:00+09:00</dc:date>
<description> </description>
</item>
</rdf:RDF>
对第一个<title>
的contents(即“これまで采coding企画”を更新しました。”进行转码时,会引发异常。)。但是同样,仅当作为服务运行时。
从启动脚本运行和从Shell运行有什么区别?为什么会出现[[Transcode错误?对我来说没有意义。
更新I
今天,我了解到main
传递给了main(int argc, char **argv, char **envp)
中的环境变量。以前不知道。我修改了程序以在启动时转储其环境变量。请参阅下面的修改后的源代码。
环境变量
NOT
相同。作为服务运行时,仅设置了以下几个变量:SHELL=/bin/bash
TERM=xterm-color
PATH=/sbin:/usr/sbin:/bin:/usr/bin
_=/mnt/swdevel/Pelican/source_build/src/overlay/testXmlTranscodeBug
PWD=/
HOME=/root
SHLVL=2
列表中明显缺少的是。请参阅下面的答案。LANG = en_US.UTF-8
Init脚本片段
STARTSCRIPT=/path/to/rssReaderProg /path/To/Test/Input/File
start() {
msg="Starting service"
writeSysLog "$msg"
echo $msg >&2
local CMD="$STARTSCRIPT &>> \"$LOGFILE\" & echo \$!"
su -c "$CMD" $RUNAS > "$PIDFILE"
chmod 644 $LOGFILE
msg='RSS service started'
echo $msg >&2
writeSysLog "$msg"
}
阅读器测试源代码
#include <stdio.h>
#include <string>
#include "xercesc/dom/DOM.hpp"
#include "xercesc/dom/DOMException.hpp"
#include "xercesc/dom/DOMNodeList.hpp"
#include "xercesc/dom/DOMNamedNodeMap.hpp"
#include "xercesc/dom/DOMNode.hpp"
#include "xercesc/dom/DOMAttr.hpp"
#include "xercesc/dom/DOMError.hpp"
#include "xercesc/dom/DOMErrorHandler.hpp"
#include "xercesc/sax/HandlerBase.hpp"
#include "xercesc/util/XMLString.hpp"
#include "xercesc/dom/DOMLocator.hpp"
#include "xercesc/parsers/XercesDOMParser.hpp"
#include "xercesc/util/OutOfMemoryException.hpp"
XERCES_CPP_NAMESPACE_USE
int
main(int argc, char **argv, char **envp)
{
printf("\n\nENV Array:\n");
for (char **env = envp; *env != 0; env++)
{
char *thisEnv = *env;
printf("%s\n", thisEnv);
}
printf("\n\n");
if (argc != 2)
{
printf("Usage: testXmlTranscodeBug <xmlFilePath>\n");
exit(1);
}
printf("initializing XML\n");
XMLPlatformUtils::Initialize();
DOMDocument *pDoc = 0;
DOMElement *pDocRoot = 0;
XercesDOMParser *pParser = new XercesDOMParser();
pParser->setValidationScheme(XercesDOMParser::Val_Always);
char *filePath = argv[1];
XMLCh *pItemTag = XMLString::transcode("item");
printf("Opening %s\n", filePath );
pParser->parse(filePath);
pDoc = pParser->getDocument();
pDocRoot = pDoc->getDocumentElement();
// Search for all the <item> child elements under pTopElem which
DOMNodeList *pItemList = pDocRoot->getElementsByTagName(pItemTag);
int numItems = pItemList->getLength();
printf("Found %d items\n", numItems );
for (int i = 0; i < numItems; i++)
{
printf(" ITEM %d\n", i);
DOMNode *pItemNode = pItemList->item(i);
DOMElement *pItemItem = ( (DOMElement *) pItemNode)->getFirstElementChild();
while (pItemItem != 0)
{
char *en = XMLString::transcode(pItemItem->getTagName());
printf(" TAG '%s'\n", en);
std::string elemName(en);
XMLString::release(&en);
// The item value (text content) is first child. It might be blank
DOMNode *pValNode = pItemItem->getFirstChild();
if (pValNode != 0)
{
printf(" pValNode = %p, print node value\n", pValNode);
const XMLCh *nodeVal = pValNode->getNodeValue();
printf(" nodeVal=%p, len=%lu\n", nodeVal, strlen((char*)nodeVal));
printf(" calling transcode. print node value\n");
char *val = 0;
try
{
val = XMLString::transcode(pValNode->getNodeValue());
}
catch (...)
{
printf(" EXCEPTION Calling XMLString::transcode()\n");
}
printf(" transcode returned [%s]\n", val);
XMLString::release(&val);
}
printf("\n");
pItemItem = pItemItem->getNextElementSibling();
}
}
}
LANG = en_US.UTF-8。
这似乎导致Xerces转码器有时因xercesc_3_2 :: TranscodingException而失败。目前,我已经将LANG=en_US.UTF-8
硬编码到程序中,并且它不再引发异常。
int
main(int argc, char **argv)
{
putenv("LANG=en_US.UTF-8");
etc...