title: Working program throws xercesc_3_2::TranscodingException when run as linux service
body: <p>I have program which reads an RSS feed using the <a href="https://xerces.apache.org/" rel="nofollow noreferrer">Xerces XML framework</a> and "does stuff" with the information it gets.</p>
  
  <p>The program works.</p>
  
  <p>However, if the program is run, in any way, via a Linux service (init.d script started as <code>service myservice.sh start</code>), the program throws an <code>xercesc_3_2::TranscodingException</code> when reading some Asian feeds.</p>
  
  <p>The exception is thrown if the program is called directly from the init script, or wrapper > myProgram or wrapper1 > wrapper2 > myProgram and so on.</p>
  
  <p>I really have no idea why the program would behave differently whether run from the command line or run from the init script.  </p>
  
  <p><strong>Environment</strong></p>
  
  <pre><code>Centos 6, 64-bit 4.4.211-1.el6.elrepo.x86_64 
  C++ '11 
  Xerces-C 3.2.1
  </code></pre>
  
  <p>Here is a minimal test case.</p>
  
  <p><strong>XML test File:</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;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/" &gt;
  &lt;item&gt;
   &lt;title&gt;「これまで採択した企画」を更新しました。&lt;/title&gt;
   &lt;link&gt;http://www.nhk.or.jp/kikakubosyuu/koremade.html?=20200430T1200&lt;/link&gt;
   &lt;dc:date&gt;2020-04-30T17:00+09:00&lt;/dc:date&gt;
   &lt;description&gt; &lt;/description&gt;
  &lt;/item&gt;
  &lt;/rdf:RDF&gt;
  </code></pre>
  
  <p>The exception is thrown when transcoding the <em>contents</em> of the first <code>&lt;title&gt;</code> (ie, "これまで採択した企画」を更新しました。"). But again, only when running as a service.</p>
  
  <p>What is different between running from an init script and from the shell?  Any why <em>Transcode</em> error?  Doesn't make sense to me.</p>
  
  <p><strong>Update I</strong></p>
  
  <p>Today I learned <code>main</code> is passed the environment variables as in <code>main(int argc, char **argv, char **envp)</code>.  Didn't know that before.</p>
  
  <p>I modified the program to dump its environment variable on startup.  See modified source code below.</p>
  
  <p>The environment variables are <strong>NOT</strong> the same.</p>
  
  <p>When running as a service, there are only these few variables set:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Notably missing from the list is <strong>LANG=en_US.UTF-8</strong>.  See my answer below.</p>
  
  <p><strong>Init Script Fragment</strong></p>
  
  <pre><code>STARTSCRIPT=/path/to/rssReaderProg /path/To/Test/Input/File
  start() {
      msg="Starting service"
      writeSysLog "$msg"
      echo $msg &gt;&amp;2
  
      local CMD="$STARTSCRIPT &amp;&gt;&gt; \"$LOGFILE\" &amp; echo \$!"
      su -c "$CMD" $RUNAS &gt; "$PIDFILE"
      chmod 644 $LOGFILE
      msg='RSS service started'
      echo $msg &gt;&amp;2
      writeSysLog "$msg"
  }
  </code></pre>
  
  <p><strong>READER TEST SOURCE CODE</strong></p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;string&gt;
  
  #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 &lt;xmlFilePath&gt;\n");
          exit(1);
      }
  
      printf("initializing XML\n");
      XMLPlatformUtils::Initialize();
  
      DOMDocument        *pDoc = 0;
      DOMElement     *pDocRoot = 0;
      XercesDOMParser *pParser = new XercesDOMParser();
      pParser-&gt;setValidationScheme(XercesDOMParser::Val_Always);
  
      char *filePath = argv[1];
      XMLCh    *pItemTag = XMLString::transcode("item");
  
      printf("Opening %s\n", filePath );
      pParser-&gt;parse(filePath);
      pDoc = pParser-&gt;getDocument();
      pDocRoot = pDoc-&gt;getDocumentElement();
  
      // Search for all the &lt;item&gt; child elements under pTopElem which
      DOMNodeList    *pItemList = pDocRoot-&gt;getElementsByTagName(pItemTag);
  
      int    numItems = pItemList-&gt;getLength();
      printf("Found %d items\n", numItems );
  
      for (int i = 0; i &lt; numItems; i++)
      {
          printf(" ITEM %d\n", i);
          DOMNode *pItemNode = pItemList-&gt;item(i);
          DOMElement *pItemItem = ( (DOMElement *) pItemNode)-&gt;getFirstElementChild();
  
          while (pItemItem != 0)
          {
              char *en = XMLString::transcode(pItemItem-&gt;getTagName());
              printf("  TAG '%s'\n", en);
              std::string elemName(en);
              XMLString::release(&amp;en);
  
              // The item value (text content) is first child. It might be blank
              DOMNode *pValNode = pItemItem-&gt;getFirstChild();
              if (pValNode != 0)
              {
                  printf("    pValNode = %p, print node value\n", pValNode);
                  const XMLCh *nodeVal =  pValNode-&gt;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-&gt;getNodeValue());
                  }
                  catch (...)
                  {
                      printf("    EXCEPTION Calling XMLString::transcode()\n");
                  }
                  printf("    transcode returned [%s]\n", val);
                  XMLString::release(&amp;val);
              }
  
              printf("\n");
              pItemItem = pItemItem-&gt;getNextElementSibling();
          }
      }
  
  }
  </code></pre>