diff options
author | Marc Laukien <marc@zeroc.com> | 2002-01-28 04:23:19 +0000 |
---|---|---|
committer | Marc Laukien <marc@zeroc.com> | 2002-01-28 04:23:19 +0000 |
commit | 83f33233414556f350cd3a8d7b1cf1af6db69457 (patch) | |
tree | 38f7ed62d4b25d660953e045d651a5f8ee1de4cf /cpp | |
parent | oneway callback test (diff) | |
download | ice-83f33233414556f350cd3a8d7b1cf1af6db69457.tar.bz2 ice-83f33233414556f350cd3a8d7b1cf1af6db69457.tar.xz ice-83f33233414556f350cd3a8d7b1cf1af6db69457.zip |
Glacier properties
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/doc/Properties.sgml | 170 | ||||
-rw-r--r-- | cpp/src/Glacier/ClientBlobject.cpp | 2 | ||||
-rw-r--r-- | cpp/src/Glacier/GlacierI.cpp | 273 | ||||
-rw-r--r-- | cpp/src/Glacier/GlacierI.h | 5 | ||||
-rw-r--r-- | cpp/src/Glacier/GlacierRouter.cpp | 9 | ||||
-rw-r--r-- | cpp/src/Glacier/GlacierStarter.cpp | 8 | ||||
-rw-r--r-- | cpp/src/Glacier/RouterI.cpp | 5 | ||||
-rw-r--r-- | cpp/src/Glacier/ServerBlobject.cpp | 2 | ||||
-rw-r--r-- | cpp/src/Ice/PropertiesI.cpp | 2 |
9 files changed, 363 insertions, 113 deletions
diff --git a/cpp/doc/Properties.sgml b/cpp/doc/Properties.sgml index 140d1daf71e..6892301d5d4 100644 --- a/cpp/doc/Properties.sgml +++ b/cpp/doc/Properties.sgml @@ -16,7 +16,7 @@ string is interpreted as zero. </para> <!-- ********************************************************************** --> -<section><title>Tracing</title> +<section><title>&Ice; Tracing Properties</title> <!-- ********************************************************************** --> <section><title>Ice.Trace.Network</title> @@ -34,7 +34,7 @@ The network tracing level: <tbody> <row> <entry>0</entry> -<entry>No network tracing.</entry> +<entry>No network tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -70,7 +70,7 @@ The protocol tracing level: <tbody> <row> <entry>0</entry> -<entry>No protocol tracing.</entry> +<entry>No protocol tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -98,7 +98,7 @@ The request retry tracing level: <tbody> <row> <entry>0</entry> -<entry>No request retry tracing.</entry> +<entry>No request retry tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -130,7 +130,7 @@ The Security extension tracing level: <tbody> <row> <entry>0</entry> -<entry>No security tracing.</entry> +<entry>No security tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -152,7 +152,7 @@ configuration file parse step. </section> <!-- ********************************************************************** --> -<section><title>Object Adapter</title> +<section><title>&Ice; Object Adapter Properties</title> <!-- ********************************************************************** --> <section><title>Ice.Adapter.<replaceable>name</replaceable>.Endpoints</title> @@ -176,7 +176,7 @@ has been created with </section> <!-- ********************************************************************** --> -<section><title>Thread Pool</title> +<section><title>&Ice; Thread Pool Properties</title> <!-- ********************************************************************** --> <section><title>Ice.ThreadPool.MaxConnections</title> @@ -214,7 +214,7 @@ The number of threads in the thread pool. Default is 10. </section> <!-- ********************************************************************** --> -<section><title>Security</title> +<section><title>&Ice; Security Properties</title> <!-- ********************************************************************** --> <section><title>Ice.Security.Ssl.CertPath</title> @@ -275,7 +275,7 @@ application data before the connection times-out and resets. </section> <!-- ********************************************************************** --> -<section><title>Protocol</title> +<section><title>&Ice; Protocol Properties</title> <!-- ********************************************************************** --> <section><title>Ice.DefaultProtocol</title> @@ -314,7 +314,7 @@ instead. The default value is the local host name. </section> <!-- ********************************************************************** --> -<section><title>Routing</title> +<section><title>&Ice; Routing Properties</title> <!-- ********************************************************************** --> <section><title>Ice.DefaultRouter</title> @@ -326,8 +326,8 @@ Ice.DefaultRouter=<replaceable>router</replaceable> <section> <title>Description</title> <para> -Specifies a default &Glacier; router (as stingified object reference -to the &Glacier; router control interface) which is to be used for all +Specifies a default router (as stingified object reference to the +&Glacier; router control interface) which is to be used for all Proxies, unless the router is overwritten with the Proxy's <literal>ice_router()</literal> operation. The default value is no router. @@ -344,10 +344,10 @@ Ice.Adapter.<replaceable>name</replaceable>.Router=<replaceable>router</replacea <section> <title>Description</title> <para> -Specifies a &Glacier; router (as stingified object reference to the -&Glacier; router control interface) for the object adapter with the -name <replaceable>name</replaceable>. By doing so, the object adapter -can receive callbacks from this router, using connections which are +Specifies a router (as stingified object reference to the &Glacier; +router control interface) for the object adapter with the name +<replaceable>name</replaceable>. By doing so, the object adapter can +receive callbacks from this router, using connections which are established from this process to the router, instead of the router having to establish a connection back to the named object adapter. <note><para> You can only specify a particular router for one single @@ -361,7 +361,7 @@ router. </para></note> </section> <!-- ********************************************************************** --> -<section><title>Miscellaneous</title> +<section><title>&Ice; Miscellaneous Properties</title> <!-- ********************************************************************** --> <section><title>Ice.Daemon, Ice.DaemonNoClose, Ice.DaemonNoChdir</title> @@ -547,7 +547,7 @@ The topic manager tracing level: <tbody> <row> <entry>0</entry> -<entry>No tracing.</entry> +<entry>No topic manager tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -575,13 +575,13 @@ IceStorm.Trace.Topic=<replaceable>num</replaceable> <section> <title>Description</title> <para> -The Topic tracing level: +The topic tracing level: <informaltable> <tgroup cols=2> <tbody> <row> <entry>0</entry> -<entry>No tracing.</entry> +<entry>No topic tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -609,7 +609,7 @@ Trace information on the thread that flushes batch reliability events to subscri <tbody> <row> <entry>0</entry> -<entry>No tracing.</entry> +<entry>No flush tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -631,13 +631,13 @@ IceStorm.Trace.Subscriber=<replaceable>num</replaceable> <section> <title>Description</title> <para> -The Subscriber tracing level: +The subscriber tracing level: <informaltable> <tgroup cols=2> <tbody> <row> <entry>0</entry> -<entry>No tracing.</entry> +<entry>No subscriber tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -671,7 +671,7 @@ property is 100 ms. </section> <!-- ********************************************************************** --> -<section><title>&Glacier; Properties</title> +<section><title>&Glacier; Router Properties</title> <!-- ********************************************************************** --> <section><title>Glacier.Router.Endpoints, Glacier.Client.Endpoints, Glacier.Server.Endpoints</title> @@ -745,7 +745,7 @@ The client interface tracing level: <tbody> <row> <entry>0</entry> -<entry>No tracing.</entry> +<entry>No client interface tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -780,7 +780,7 @@ The server interface tracing level: <tbody> <row> <entry>0</entry> -<entry>No tracing.</entry> +<entry>No server interface tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -815,7 +815,7 @@ The routing table tracing level: <tbody> <row> <entry>0</entry> -<entry>No tracing.</entry> +<entry>No routing table tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -832,6 +832,118 @@ The routing table tracing level: </section> <!-- ********************************************************************** --> +<section><title>&Glacier; Router Starter Properties</title> +<!-- ********************************************************************** --> + +<section><title>Glacier.Starter.Endpoints</title> +<section><title>Synopsis</title> +<synopsis> +Glacier.Starter.Endpoints=<replaceable>endpoints</replaceable> +</synopsis> +</section> +<section> +<title>Description</title> +<para> +Defines the endpoints of the &Glacier; router starter. (Unix only.) +</para> +</section> +</section> + +<section><title>Glacier.Starter.RouterPath</title> +<section><title>Synopsis</title> +<synopsis> +Glacier.Starter.RouterPath=<replaceable>path</replaceable> +</synopsis> +</section> +<section> +<title>Description</title> +<para> +Sets the path of the &Glacier; router executable to be started. The +default is <literal>glacier</literal>. (Unix only.) +</para> +</section> +</section> + +<section><title>Glacier.Starter.PropertiesOverwrite</title> +<section><title>Synopsis</title> +<synopsis> +Glacier.Starter.PropertiesOverwrite=<replaceable>overwrites</replaceable> +</synopsis> +</section> +<section> +<title>Description</title> +<para> +By default, the &Glacier; router starter starts new routers with the +exact same property set as for the router +starter. <replaceable>overwrites</replaceable> can contain a list +(separated by whitespace) of properties for the router, which are used +in addition to the router starter's properties, or which overwrite the +router starter's properties. For example, in many cases it is +desirable to set the property <literal>Ice.ServerIdleTime</literal> +for the router, but not for the router starter. For an idle time of 60 +seconds, this can be done by setting +<literal>Glacier.Starter.PropertiesOverwrite=Ice.SeverIdleTime=60</literal>. (Unix +only.) +</para> +</section> +</section> + +<section><title>Glacier.Starter.StartupTimeout</title> +<section><title>Synopsis</title> +<synopsis> +Glacier.Starter.StartupTimeout=<replaceable>num</replaceable> +</synopsis> +</section> +<section> +<title>Description</title> +<para> +<replaceable>num</replaceable> is the number of seconds the &Glacier; +router starter will wait for the router to start up. If this timeout +expires, a <literal>Glacier::CannotStartRouterException</literal> is +returned to the caller. The default value is 10 seconds. Timeout +values smaller than one second are silently changed to 1 second. (Unix +only.) +</para> +</section> +</section> + +<section><title>Glacier.Trace.Starter</title> +<section><title>Synopsis</title> +<synopsis> +Glacier.Trace.Starter=<replaceable>num</replaceable> +</synopsis> +</section> +<section> +<title>Description</title> +<para> +The router starter tracing level: (Unix only.) +<informaltable> +<tgroup cols=2> +<tbody> +<row> +<entry>0</entry> +<entry>No router starter tracing. (default)</entry> +</row> +<row> +<entry>1</entry> +<entry>Trace router startup exceptions. +</entry> +</row> +<row> +<entry>2</entry> +<entry>Trace also each successful router startup. +</entry> +</row> +</tbody> +</tgroup> +</informaltable> +</para> +</section> +</section> + +</section> + +<!-- ********************************************************************** --> <section><title>&Freeze; Properties</title> <!-- ********************************************************************** --> @@ -850,7 +962,7 @@ The &Freeze; database activity tracing level: <tbody> <row> <entry>0</entry> -<entry>No database activity tracing.</entry> +<entry>No database activity tracing. (default)</entry> </row> <row> <entry>1</entry> @@ -882,7 +994,7 @@ The &Freeze; evictor activity tracing level: <tbody> <row> <entry>0</entry> -<entry>No evictor activity tracing.</entry> +<entry>No evictor activity tracing. (default)</entry> </row> <row> <entry>1</entry> diff --git a/cpp/src/Glacier/ClientBlobject.cpp b/cpp/src/Glacier/ClientBlobject.cpp index 9cd92e4a459..b8cf3dd76cb 100644 --- a/cpp/src/Glacier/ClientBlobject.cpp +++ b/cpp/src/Glacier/ClientBlobject.cpp @@ -33,8 +33,10 @@ Glacier::ClientBlobject::~ClientBlobject() void Glacier::ClientBlobject::destroy() { + // // No mutex protection necessary, destroy is only called after all // object adapters have shut down. + // _communicator = 0; _logger = 0; _routingTable = 0; diff --git a/cpp/src/Glacier/GlacierI.cpp b/cpp/src/Glacier/GlacierI.cpp index 0d2ef4a4c2c..82861ada133 100644 --- a/cpp/src/Glacier/GlacierI.cpp +++ b/cpp/src/Glacier/GlacierI.cpp @@ -22,13 +22,30 @@ using namespace Ice; using namespace Glacier; Glacier::StarterI::StarterI(const CommunicatorPtr& communicator) : - _communicator(communicator) + _communicator(communicator), + _logger(_communicator->getLogger()), + _properties(_communicator->getProperties()) { + _traceLevel = atoi(_properties->getProperty("Glacier.Trace.Starter").c_str()); +} + +void +Glacier::StarterI::destroy() +{ + // + // No mutex protection necessary, destroy is only called after all + // object adapters have shut down. + // + _communicator = 0; + _logger = 0; + _properties = 0; } RouterPrx Glacier::StarterI::startRouter(const string& userId, const string& password, const Current&) { + assert(_communicator); // Destroyed? + // // TODO: userId/password check // @@ -36,82 +53,131 @@ Glacier::StarterI::startRouter(const string& userId, const string& password, con // // Start a router // + string path = _properties->getProperty("Glacier.Starter.RouterPath"); + if (path.empty()) + { + path = "glacier"; + } + string uuid = IceUtil::generateUUID(); - char buf[4*1024]; + pid_t pid; + int fds[2]; + try { - int fds[2]; if (pipe(fds) != 0) { SystemException ex(__FILE__, __LINE__); ex.error = getSystemErrno(); throw ex; } - pid_t pid = fork(); + pid = fork(); if (pid == -1) { SystemException ex(__FILE__, __LINE__); ex.error = getSystemErrno(); throw ex; } - if (pid == 0) // Child process + } + catch(const LocalException& ex) + { + ostringstream s; + s << ex; + _logger->error(s.str()); + + ex.ice_throw(); + } + + if (pid == 0) // Child process + { + // + // Close all filedescriptors, except for standard input, + // standard output, standard error output, and the write side + // of the newly created pipe. + // + int maxFd = static_cast<int>(sysconf(_SC_OPEN_MAX)); + for (int fd = 3; fd < maxFd; ++fd) { - // - // Close all filedescriptors, except for standard input, - // standard output, standard error output, and the write side - // of the newly created pipe. - // - int maxFd = static_cast<int>(sysconf(_SC_OPEN_MAX)); - for (int fd = 3; fd < maxFd; ++fd) + if (fd != fds[1]) { - if (fd != fds[1]) - { - close(fd); - } + close(fd); } - - // - // Setup arguments to start the router with. - // - StringSeq args = _communicator->getProperties()->getCommandLineOptions(); - args.push_back("--Glacier.Router.Identity=" + uuid); - ostringstream s; - s << "--Glacier.Router.PrintProxyOnFd=" << fds[1]; - args.push_back(s.str()); - - // - // Convert to standard argc/argv. - // - int argc = args.size() + 1; - char** argv = static_cast<char**>(malloc((argc + 1) * sizeof(char*))); - StringSeq::iterator p; - int i; - for (p = args.begin(), i = 1; p != args.end(); ++p, ++i) + } + + // + // Setup arguments to start the router with. + // + StringSeq args = _properties->getCommandLineOptions(); + args.push_back("--Glacier.Router.Identity=" + uuid); + ostringstream s; + s << "--Glacier.Router.PrintProxyOnFd=" << fds[1]; + args.push_back(s.str()); + string overwrite = _properties->getProperty("Glacier.Starter.PropertiesOverwrite"); + if (!overwrite.empty()) + { + string::size_type end = 0; + while (end != string::npos) { - assert(i < argc); - argv[i] = strdup(p->c_str()); + static const string delim = " \t\r\n"; + + string::size_type beg = overwrite.find_first_not_of(delim, end); + if (beg == string::npos) + { + break; + } + + end = overwrite.find_first_of(delim, beg); + string arg; + if (end == string::npos) + { + arg = overwrite.substr(beg); + } + else + { + arg = overwrite.substr(beg, end - beg); + } + if (arg.find("--") != 0) + { + arg = "--" + arg; + } + args.push_back(arg); } - assert(i == argc); - argv[0] = strdup("glacier"); // TODO: Property - argv[argc] = 0; - + } + + // + // Convert to standard argc/argv. + // + int argc = args.size() + 1; + char** argv = static_cast<char**>(malloc((argc + 1) * sizeof(char*))); + StringSeq::iterator p; + int i; + for (p = args.begin(), i = 1; p != args.end(); ++p, ++i) + { + assert(i < argc); + argv[i] = strdup(p->c_str()); + } + assert(i == argc); + argv[0] = strdup(path.c_str()); + argv[argc] = 0; + + // + // Try to start the router. + // + if (execvp(argv[0], argv) == -1) + { // - // Try to start the router. + // Send any errors to the parent process, using the write + // end of the pipe. // - if (execvp(argv[0], argv) == -1) - { - // - // Send any errors to the parent process, using the write - // end of the pipe. - // - ostringstream s; - s << "can't execute `" << argv[0] << "': " << strerror(errno); - write(fds[1], s.str().c_str(), s.str().length()); - close(fds[1]); - exit(EXIT_FAILURE); - } + string msg = "can't execute `" + path + "': " + strerror(errno); + write(fds[1], msg.c_str(), msg.length()); + close(fds[1]); + exit(EXIT_FAILURE); } - else // Parent process + } + else // Parent process + { + try { // // Close the write side of the newly created pipe @@ -136,7 +202,19 @@ Glacier::StarterI::startRouter(const string& userId, const string& password, con FD_ZERO(&fdSet); FD_SET(fds[0], &fdSet); struct timeval tv; - tv.tv_sec = 5; // TODO: Property + string timeout = _properties->getProperty("Glacier.Starter.StartupTimeout"); + if (timeout.empty()) + { + tv.tv_sec = 10; // 10 seconds default. + } + else + { + tv.tv_sec = atoi(timeout.c_str()); + if (tv.tv_sec < 1) + { + tv.tv_sec = 1; // One second is minimum. + } + } tv.tv_usec = 0; int ret = ::select(fds[0] + 1, &fdSet, 0, 0, &tv); @@ -154,7 +232,9 @@ Glacier::StarterI::startRouter(const string& userId, const string& password, con if (ret == 0) // Timeout { - assert(false); // TODO: Handle this situation. + CannotStartRouterException ex; + ex.reason = "timeout while starting `" + path + "'"; + throw ex; } assert(FD_ISSET(fds[0], &fdSet)); @@ -162,6 +242,7 @@ Glacier::StarterI::startRouter(const string& userId, const string& password, con // // Read the response // + char buf[4*1024]; ssize_t sz = read(fds[0], buf, sizeof(buf)/sizeof(char) - 1); if(sz == -1) { @@ -169,33 +250,63 @@ Glacier::StarterI::startRouter(const string& userId, const string& password, con ex.error = getSystemErrno(); throw ex; } - assert(sz != 0); // TODO: Handle EOF + + if (sz == 0) // EOF? + { + CannotStartRouterException ex; + ex.reason = "got EOF from `" + path + "'"; + throw ex; + } + buf[sz] = '\0'; // Terminate the string we got back. + + if (strncmp(buf, uuid.c_str(), uuid.length()) == 0) + { + // + // We got the stringified router proxy. + // + RouterPrx router = RouterPrx::uncheckedCast(_communicator->stringToProxy(buf)); + + if (_traceLevel >= 2) + { + ostringstream s; + s << "started new router:\n" << _communicator->proxyToString(router); + _logger->trace("Glacier", s.str()); + } + + return router; + } + else + { + // + // We got something else. + // + CannotStartRouterException ex; + ex.reason = buf; + throw ex; + } } - } - catch(const LocalException& ex) - { - // TODO: Log exception or print warning - cerr << ex << endl; - ex.ice_throw(); - } + catch(const CannotStartRouterException& ex) + { + if (_traceLevel >= 1) + { + ostringstream s; + s << "router starter exception:\n" << ex << ":\n" << ex.reason; + _logger->trace("Glacier", s.str()); + } + + ex.ice_throw(); + } + catch(const Exception& ex) + { + ostringstream s; + s << ex; + _logger->error(s.str()); - if (strncmp(buf, uuid.c_str(), uuid.length()) == 0) - { - // - // We got the stringified router proxy. - // - return RouterPrx::uncheckedCast(_communicator->stringToProxy(buf)); - } - else - { - // - // We got something else. - // - CannotStartRouterException ex; - ex.reason = buf; - // TODO: Log exception. - cerr << ex << endl; - throw ex; + ex.ice_throw(); + } } + + assert(false); // Should never be reached. + return 0; // To keep the compiler from complaining. } diff --git a/cpp/src/Glacier/GlacierI.h b/cpp/src/Glacier/GlacierI.h index 34bbddb26be..f28d542f560 100644 --- a/cpp/src/Glacier/GlacierI.h +++ b/cpp/src/Glacier/GlacierI.h @@ -23,11 +23,16 @@ public: StarterI(const Ice::CommunicatorPtr&); + void destroy(); + Ice::RouterPrx startRouter(const std::string&, const std::string&, const Ice::Current&); private: Ice::CommunicatorPtr _communicator; + Ice::LoggerPtr _logger; + Ice::PropertiesPtr _properties; + int _traceLevel; }; } diff --git a/cpp/src/Glacier/GlacierRouter.cpp b/cpp/src/Glacier/GlacierRouter.cpp index 887fc2c3b2d..353bb50c300 100644 --- a/cpp/src/Glacier/GlacierRouter.cpp +++ b/cpp/src/Glacier/GlacierRouter.cpp @@ -206,6 +206,15 @@ Glacier::Router::run(int argc, char* argv[]) { cerr << appName() << ": cannot write stringified router proxy to filedescriptor " << fd << ": " << strerror(errno) << endl; + + // + // Destroy the router. The client and server blobjects get + // destroyed by ServantLocator::deactivate. + // + RouterI* rtr = dynamic_cast<RouterI*>(router.get()); + assert(rtr); + rtr->destroy(); + return EXIT_FAILURE; } close(fd); diff --git a/cpp/src/Glacier/GlacierStarter.cpp b/cpp/src/Glacier/GlacierStarter.cpp index ea00a323196..4f0280e167c 100644 --- a/cpp/src/Glacier/GlacierStarter.cpp +++ b/cpp/src/Glacier/GlacierStarter.cpp @@ -85,6 +85,14 @@ Glacier::Router::run(int argc, char* argv[]) // We're done, let's wait for shutdown. // communicator()->waitForShutdown(); + + // + // Destroy the starter. + // + StarterI* st = dynamic_cast<StarterI*>(starter.get()); + assert(st); + st->destroy(); + return EXIT_SUCCESS; } diff --git a/cpp/src/Glacier/RouterI.cpp b/cpp/src/Glacier/RouterI.cpp index a4cb32406f0..96b8fb03ab6 100644 --- a/cpp/src/Glacier/RouterI.cpp +++ b/cpp/src/Glacier/RouterI.cpp @@ -35,8 +35,10 @@ Glacier::RouterI::~RouterI() void Glacier::RouterI::destroy() { + // // No mutex protection necessary, destroy is only called after all // object adapters have shut down. + // _clientAdapter = 0; _serverAdapter = 0; _logger = 0; @@ -74,8 +76,7 @@ Glacier::RouterI::addProxy(const ObjectPrx& proxy, const Current&) if (_routingTableTraceLevel) { ostringstream s; - s << "adding proxy to routing table:\n" - << _clientAdapter->getCommunicator()->proxyToString(proxy); + s << "adding proxy to routing table:\n" << _clientAdapter->getCommunicator()->proxyToString(proxy); _logger->trace("Glacier", s.str()); } diff --git a/cpp/src/Glacier/ServerBlobject.cpp b/cpp/src/Glacier/ServerBlobject.cpp index 16d3ae71c01..785191963f6 100644 --- a/cpp/src/Glacier/ServerBlobject.cpp +++ b/cpp/src/Glacier/ServerBlobject.cpp @@ -31,8 +31,10 @@ Glacier::ServerBlobject::~ServerBlobject() void Glacier::ServerBlobject::destroy() { + // // No mutex protection necessary, destroy is only called after all // object adapters have shut down. + // _clientAdapter = 0; _logger = 0; } diff --git a/cpp/src/Ice/PropertiesI.cpp b/cpp/src/Ice/PropertiesI.cpp index 06e13051d4e..96dc5cf9cb4 100644 --- a/cpp/src/Ice/PropertiesI.cpp +++ b/cpp/src/Ice/PropertiesI.cpp @@ -198,7 +198,7 @@ Ice::PropertiesI::parse(istream& in) void Ice::PropertiesI::parseLine(const string& line) { - const string delim = " \t"; + static const string delim = " \t\r\n"; string s = line; string::size_type idx = s.find('#'); |