diff options
author | Bernard Normier <bernard@zeroc.com> | 2009-01-23 17:07:21 -0500 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2009-01-23 17:07:21 -0500 |
commit | 2380e089401d048490da23bc6d71e5687bafbe47 (patch) | |
tree | 6d97052d1f93bc2bafcd7fd1a9ebe103544b6cad /cpp/src/IceGrid/Activator.cpp | |
parent | Fixed permissions (diff) | |
parent | 3.3.1 third-party updates (diff) | |
download | ice-2380e089401d048490da23bc6d71e5687bafbe47.tar.bz2 ice-2380e089401d048490da23bc6d71e5687bafbe47.tar.xz ice-2380e089401d048490da23bc6d71e5687bafbe47.zip |
Merge branch 'R3_3_branch' of cvs:/home/git/ice into R3_3_branch
Conflicts:
java/resources/IceGridAdmin/icegridadmin_content_dyn.html
java/resources/IceGridAdmin/icegridadmin_content_static.html
Diffstat (limited to 'cpp/src/IceGrid/Activator.cpp')
-rw-r--r-- | cpp/src/IceGrid/Activator.cpp | 169 |
1 files changed, 119 insertions, 50 deletions
diff --git a/cpp/src/IceGrid/Activator.cpp b/cpp/src/IceGrid/Activator.cpp index d585a11eb15..0b99b68a417 100644 --- a/cpp/src/IceGrid/Activator.cpp +++ b/cpp/src/IceGrid/Activator.cpp @@ -1,6 +1,6 @@ // ********************************************************************** // -// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved. +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. @@ -514,8 +514,7 @@ Activator::activate(const string& name, string::size_type pos = s.find('='); if(pos != string::npos) { - string key = s.substr(0, pos); - std::transform(key.begin(), key.end(), key.begin(), toupper); + string key = IceUtilInternal::toUpper(s.substr(0, pos)); envMap.insert(map<string, string>::value_type(key, s.substr(pos + 1))); } var += s.size(); @@ -528,8 +527,7 @@ Activator::activate(const string& name, string::size_type pos = s.find('='); if(pos != string::npos) { - string key = s.substr(0, pos); - std::transform(key.begin(), key.end(), key.begin(), toupper); + string key = IceUtilInternal::toUpper(s.substr(0, pos)); envMap.erase(key); envMap.insert(map<string, string>::value_type(key, s.substr(pos + 1))); } @@ -610,6 +608,15 @@ Activator::activate(const string& name, throw ex; } + int errorFds[2]; + if(pipe(errorFds) != 0) + { + SyscallException ex(__FILE__, __LINE__); + ex.error = getSystemErrno(); + throw ex; + } + + // // Convert to standard argc/argv. // @@ -652,14 +659,14 @@ Activator::activate(const string& name, { ostringstream os; os << gid; - reportChildError(getSystemErrno(), fds[1], "cannot set process group id", os.str().c_str()); + reportChildError(getSystemErrno(), errorFds[1], "cannot set process group id", os.str().c_str()); } if(setuid(uid) == -1) { ostringstream os; os << uid; - reportChildError(getSystemErrno(), fds[1], "cannot set process user id", os.str().c_str()); + reportChildError(getSystemErrno(), errorFds[1], "cannot set process user id", os.str().c_str()); } // @@ -675,7 +682,7 @@ Activator::activate(const string& name, int maxFd = static_cast<int>(sysconf(_SC_OPEN_MAX)); for(int fd = 3; fd < maxFd; ++fd) { - if(fd != fds[1]) + if(fd != fds[1] && fd != errorFds[1]) { close(fd); } @@ -688,7 +695,7 @@ Activator::activate(const string& name, // if(putenv(strdup(env.argv[i])) != 0) { - reportChildError(errno, fds[1], "cannot set environment variable", env.argv[i]); + reportChildError(errno, errorFds[1], "cannot set environment variable", env.argv[i]); } } @@ -699,18 +706,65 @@ Activator::activate(const string& name, { if(chdir(pwdCStr) == -1) { - reportChildError(errno, fds[1], "cannot change working directory to", pwdCStr); + reportChildError(errno, errorFds[1], "cannot change working directory to", pwdCStr); } } + // + // Close on exec the error message file descriptor. + // + int flags = fcntl(errorFds[1], F_GETFD); + flags |= 1; // FD_CLOEXEC + if(fcntl(errorFds[1], F_SETFD, flags) == -1) + { + close(errorFds[1]); + errorFds[1] = -1; + } + if(execvp(av.argv[0], av.argv) == -1) { - reportChildError(errno, fds[1], "cannot execute", av.argv[0]); + if(errorFds[1] != -1) + { + reportChildError(errno, errorFds[1], "cannot execute", av.argv[0]); + } + else + { + reportChildError(errno, fds[1], "cannot execute", av.argv[0]); + } } } else // Parent process. { close(fds[1]); + close(errorFds[1]); + + // + // Read a potential error message over the error message pipe. + // + char s[16]; + ssize_t rs; + string message; + while((rs = read(errorFds[0], &s, 16)) > 0) + { + message.append(s, rs); + } + + // + // If an error occured before the exec() we do some cleanup and throw. + // + if(!message.empty()) + { + close(fds[0]); + close(errorFds[0]); + waitPid(pid); + throw message; + } + + // + // Otherwise, the exec() was successfull and we don't need the error message + // pipe anymore. + // + close(errorFds[0]); Process process; process.pid = pid; @@ -1005,6 +1059,13 @@ Activator::destroy() assert(_processes.empty()); } +bool +Activator::isActive() +{ + IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); + return !_deactivating; +} + void Activator::runTerminationListener() { @@ -1245,45 +1306,7 @@ Activator::terminationListener() for(vector<Process>::const_iterator p = terminated.begin(); p != terminated.end(); ++p) { - int status; -#if defined(__linux) - int nRetry = 0; - while(true) // The while loop is necessary for the linux workaround. - { - pid_t pid = waitpid(p->pid, &status, 0); - if(pid < 0) - { - // - // Some Linux distribution have a bogus waitpid() (e.g.: CentOS 4.x). It doesn't - // block and reports an incorrect ECHILD error on the first call. We sleep a - // little and retry to work around this issue (it appears from testing that a - // single retry is enough but to make sure we retry up to 10 times before to throw.) - // - if(errno == ECHILD && nRetry < 10) - { - // Wait 1ms, 11ms, 21ms, etc. - IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(nRetry * 10 + 1)); - ++nRetry; - continue; - } - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - assert(pid == p->pid); - break; - } -#else - pid_t pid = waitpid(p->pid, &status, 0); - if(pid < 0) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - assert(pid == p->pid); -#endif - + int status = waitPid(p->pid); if(_traceLevels->activator > 0) { Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); @@ -1343,3 +1366,49 @@ Activator::setInterrupt() write(_fdIntrWrite, &c, 1); #endif } + +#ifndef _WIN32 +int +Activator::waitPid(pid_t processPid) +{ + int status; +#if defined(__linux) + int nRetry = 0; + while(true) // The while loop is necessary for the linux workaround. + { + pid_t pid = waitpid(processPid, &status, 0); + if(pid < 0) + { + // + // Some Linux distribution have a bogus waitpid() (e.g.: CentOS 4.x). It doesn't + // block and reports an incorrect ECHILD error on the first call. We sleep a + // little and retry to work around this issue (it appears from testing that a + // single retry is enough but to make sure we retry up to 10 times before to throw.) + // + if(errno == ECHILD && nRetry < 10) + { + // Wait 1ms, 11ms, 21ms, etc. + IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(nRetry * 10 + 1)); + ++nRetry; + continue; + } + SyscallException ex(__FILE__, __LINE__); + ex.error = getSystemErrno(); + throw ex; + } + assert(pid == processPid); + break; + } +#else + pid_t pid = waitpid(processPid, &status, 0); + if(pid < 0) + { + SyscallException ex(__FILE__, __LINE__); + ex.error = getSystemErrno(); + throw ex; + } + assert(pid == processPid); +#endif + return status; +} +#endif |