我有一个程序,它使用Xerces XML框架读取一个RSS提要,并使用它获得的信息“做一些事情”。
这个程序很管用。
但是,如果程序以任何方式通过Linux服务运行(init.d脚本启动为service myservice.sh start),则程序在读取某些亚洲提要时抛出一个xercesc_3_2::TranscodingException。
如果程序直接从init脚本调用,或者包装器> 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> (即“これまで採択した企画”を更新しました“)的内容时,会引发异常。。但同样,只有在作为服务运行的情况下。
从init脚本运行和从shell运行有什么不同?翻译错误有什么原因吗?对我来说没有意义。
更新I
今天,我了解了main是传递环境变量的,就像在main(int argc, char **argv, char **envp)中一样。以前都不知道。
我修改了程序,以便在启动时转储它的环境变量。请参阅下面修改的源代码。
环境变量是,而不是。
在作为服务运行时,只有以下几个变量集:
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();
}
}
}发布于 2020-05-04 01:49:36
当作为服务启动时,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...https://stackoverflow.com/questions/61574460
复制相似问题