Рабочая программа выдает xercesc_3_2 :: TranscodingException при запуске как linux сервис - PullRequest
0 голосов
/ 03 мая 2020

У меня есть программа, которая читает 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();
        }
    }

}

1 Ответ

0 голосов
/ 04 мая 2020

При запуске в качестве службы 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...
...