У меня есть программа, которая читает RSS-канал с использованием Xerces XML framework и «делает вещи» с получаемой информацией.
Программа работает.
Однако, если программа каким-либо образом запускается через службу Linux (скрипт init.d запускается как service myservice.sh start
), программа выдает xercesc_3_2::TranscodingException
при чтении некоторых азиатских каналов.
Исключение выдается, если программа вызывается напрямую из сценария инициализации, или wrapper> myProgram, или wrapper1> wrapper2> myProgram и т. Д. командной строки или запустить из сценария инициализации.
Среда
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>
(ie, " Но опять же, только при запуске в качестве службы.
Чем отличается запуск из сценария инициализации и оболочки? Любая, почему Transcode ошибка? Не имеет смысла для меня.
Обновление 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 . См. Мой ответ ниже.
Фрагмент сценария инициализации
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();
}
}
}