diff options
author | Benoit Foucher <benoit@zeroc.com> | 2004-06-02 21:17:40 +0000 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2004-06-02 21:17:40 +0000 |
commit | c209ff436f4268b8db689a2dd17615456eea78ce (patch) | |
tree | 5feb8607988706851bfdfdd5ba2d3924ba5b8f6c /cpp/src/IcePack/ActivatorI.cpp | |
parent | Fixed to AMD code generation. (diff) | |
download | ice-c209ff436f4268b8db689a2dd17615456eea78ce.tar.bz2 ice-c209ff436f4268b8db689a2dd17615456eea78ce.tar.xz ice-c209ff436f4268b8db689a2dd17615456eea78ce.zip |
Merged icepack_refactoring2_branch, many IcePack changes.
Diffstat (limited to 'cpp/src/IcePack/ActivatorI.cpp')
-rw-r--r-- | cpp/src/IcePack/ActivatorI.cpp | 1492 |
1 files changed, 0 insertions, 1492 deletions
diff --git a/cpp/src/IcePack/ActivatorI.cpp b/cpp/src/IcePack/ActivatorI.cpp deleted file mode 100644 index ce640501f8e..00000000000 --- a/cpp/src/IcePack/ActivatorI.cpp +++ /dev/null @@ -1,1492 +0,0 @@ -// ********************************************************************** -// -// Copyright (c) 2003-2004 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. -// -// ********************************************************************** - -#include <Ice/Ice.h> -#include <IcePack/ActivatorI.h> -#include <IcePack/Admin.h> -#include <IcePack/Internal.h> -#include <IcePack/TraceLevels.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <signal.h> -#include <fcntl.h> - - -using namespace std; -using namespace Ice; -using namespace IcePack; - -namespace IcePack -{ - -class TerminationListenerThread : public IceUtil::Thread -{ -public: - - TerminationListenerThread(ActivatorI& activator) : - _activator(activator) - { - } - - virtual - void run() - { - _activator.runTerminationListener(); - } - -private: - - ActivatorI& _activator; -}; - -} - -#define ICE_STRING(X) #X - -namespace -{ - -#ifndef _WIN32 -// -// Helper function for async-signal safe error reporting -// -void -reportChildError(int err, int fd, const char* cannot, const char* name) -{ - // - // Send any errors to the parent process, using the write end of - // the pipe. - // - char msg[500]; - strcpy(msg, cannot); - strcat(msg, " `"); - strcat(msg, name); - strcat(msg, "': "); - strcat(msg, strerror(err)); - write(fd, msg, strlen(msg)); - close(fd); - - // - // _exit instead of exit to avoid interferences with the parent - // process. - // - _exit(EXIT_FAILURE); -} - -#endif - -#ifndef _WIN32 -string -signalToString(int signal) -{ - switch(signal) - { - case SIGHUP: - { - return ICE_STRING(SIGHUP); - } - case SIGINT: - { - return ICE_STRING(SIGINT); - } - case SIGQUIT: - { - return ICE_STRING(SIGQUIT); - } - case SIGILL: - { - return ICE_STRING(SIGILL); - } - case SIGTRAP: - { - return ICE_STRING(SIGTRAP); - } - case SIGABRT: - { - return ICE_STRING(SIGABRT); - } - case SIGBUS: - { - return ICE_STRING(SIGBUS); - } - case SIGFPE: - { - return ICE_STRING(SIGFPE); - } - case SIGKILL: - { - return ICE_STRING(SIGKILL); - } - case SIGUSR1: - { - return ICE_STRING(SIGUSR1); - } - case SIGSEGV: - { - return ICE_STRING(SIGSEGV); - } - case SIGPIPE: - { - return ICE_STRING(SIGPIPE); - } - case SIGALRM: - { - return ICE_STRING(SIGALRM); - } - case SIGTERM: - { - return ICE_STRING(SIGTERM); - } - default: - { - ostringstream os; - os << "signal " << signal; - return os.str(); - } - } -#endif -} - -int -stringToSignal(const string& str) -{ -#ifdef _WIN32 - throw BadSignalException(); -#else - - if(str == ICE_STRING(SIGHUP)) - { - return SIGHUP; - } - else if(str == ICE_STRING(SIGINT)) - { - return SIGINT; - } - else if(str == ICE_STRING(SIGQUIT)) - { - return SIGQUIT; - } - else if(str == ICE_STRING(SIGILL)) - { - return SIGILL; - } - else if(str == ICE_STRING(SIGTRAP)) - { - return SIGTRAP; - } - else if(str == ICE_STRING(SIGABRT)) - { - return SIGABRT; - } - else if(str == ICE_STRING(SIGBUS)) - { - return SIGBUS; - } - else if(str == ICE_STRING(SIGFPE)) - { - return SIGFPE; - } - else if(str == ICE_STRING(SIGKILL)) - { - return SIGKILL; - } - else if(str == ICE_STRING(SIGUSR1)) - { - return SIGUSR1; - } - else if(str == ICE_STRING(SIGSEGV)) - { - return SIGSEGV; - } - else if(str == ICE_STRING(SIGUSR2)) - { - return SIGUSR2; - } - else if(str == ICE_STRING(SIGPIPE)) - { - return SIGPIPE; - } - else if(str == ICE_STRING(SIGALRM)) - { - return SIGALRM; - } - else if(str == ICE_STRING(SIGTERM)) - { - return SIGTERM; - } - else - { - if(str != "") - { - char* end; - long int signal = strtol(str.c_str(), &end, 10); - if(*end == '\0' && signal > 0 && signal < 64) - { - return static_cast<int>(signal); - } - } - throw BadSignalException(); - } -} -#endif - -} - -IcePack::ActivatorI::ActivatorI(const TraceLevelsPtr& traceLevels, const PropertiesPtr& properties) : - _traceLevels(traceLevels), - _properties(properties), - _deactivating(false) -{ -#ifdef _WIN32 - _hIntr = CreateEvent( - NULL, // Security attributes - TRUE, // Manual reset - FALSE, // Initial state is nonsignaled - NULL // Unnamed - ); - - if(_hIntr == NULL) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } -#else - int fds[2]; - if(pipe(fds) != 0) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - _fdIntrRead = fds[0]; - _fdIntrWrite = fds[1]; - int flags = fcntl(_fdIntrRead, F_GETFL); - flags |= O_NONBLOCK; - fcntl(_fdIntrRead, F_SETFL, flags); -#endif - - _outputDir = _properties->getProperty("IcePack.Node.Output"); - _redirectErrToOut = (_properties->getPropertyAsInt("IcePack.Node.RedirectErrToOut") > 0); - - // - // Parse the properties override property. - // - string props = _properties->getProperty("IcePack.Node.PropertiesOverride"); - if(!props.empty()) - { - string::size_type end = 0; - while(end != string::npos) - { - const string delim = " \t\r\n"; - - string::size_type beg = props.find_first_not_of(delim, end); - if(beg == string::npos) - { - break; - } - - end = props.find_first_of(delim, beg); - string arg; - if(end == string::npos) - { - arg = props.substr(beg); - } - else - { - arg = props.substr(beg, end - beg); - } - if(arg.find("--") != 0) - { - arg = "--" + arg; - } - _propertiesOverride.push_back(arg); - } - } -} - -IcePack::ActivatorI::~ActivatorI() -{ - assert(!_thread); - -#ifdef _WIN32 - if(_hIntr != NULL) - { - CloseHandle(_hIntr); - } -#else - close(_fdIntrRead); - close(_fdIntrWrite); -#endif -} - -bool -IcePack::ActivatorI::activate(const ServerPtr& server) -{ - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - - if(_deactivating) - { - return false; - } - - string path = server->description.path; - if(path.empty()) - { - return false; - } - - string pwd = server->description.pwd; - -#ifdef _WIN32 - // - // Get the absolute pathname of the executable. - // - char absbuf[_MAX_PATH]; - char* filePart; - if(SearchPath(NULL, path.c_str(), ".exe", _MAX_PATH, absbuf, &filePart) == 0) - { - Error out(_traceLevels->logger); - out << "cannot convert `" << path << "' into an absolute path"; - return false; - } - path = absbuf; - - // - // Get the absolute pathname of the working directory. - // - if(!pwd.empty()) - { - if(_fullpath(absbuf, pwd.c_str(), _MAX_PATH) == NULL) - { - Error out(_traceLevels->logger); - out << "cannot convert `" << pwd << "' into an absolute path"; - return false; - } - pwd = absbuf; - } -#else - // - // Normalize the pathname a bit. - // - { - string::size_type pos; - while((pos = path.find("//")) != string::npos) - { - path.erase(pos, 1); - } - while((pos = path.find("/./")) != string::npos) - { - path.erase(pos, 2); - } - } - - // - // Normalize the path to the working directory. - // - if(!pwd.empty()) - { - string::size_type pos; - while((pos = pwd.find("//")) != string::npos) - { - pwd.erase(pos, 1); - } - while((pos = pwd.find("/./")) != string::npos) - { - pwd.erase(pos, 2); - } - } -#endif - - // - // Setup arguments. - // - StringSeq args; - args.push_back(path); - args.insert(args.end(), server->description.args.begin(), server->description.args.end()); - args.insert(args.end(), _propertiesOverride.begin(), _propertiesOverride.end()); - args.push_back("--Ice.Default.Locator=" + _properties->getProperty("Ice.Default.Locator")); - args.push_back("--Ice.ServerId=" + server->description.name); - - if(_traceLevels->activator > 1) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "activating server `" << server->description.name << "'"; - if(_traceLevels->activator > 2) - { - out << "\n"; - out << "path = " << path << "\n"; - out << "pwd = " << pwd << "\n"; - out << "args = "; - - StringSeq::const_iterator p = args.begin(); - ++p; - for(StringSeq::const_iterator q = p; q != args.end(); ++q) - { - out << " " << *q; - } - } - } - - // - // Activate and create. - // -#ifdef _WIN32 - // - // Compose command line. - // - string cmd; - StringSeq::const_iterator p; - for(p = args.begin(); p != args.end(); ++p) - { - if(p != args.begin()) - { - cmd.push_back(' '); - } - // - // Enclose arguments containing spaces in double quotes. - // - if((*p).find(' ') != string::npos) - { - cmd.push_back('"'); - cmd.append(*p); - cmd.push_back('"'); - } - else - { - cmd.append(*p); - } - } - - const char* dir; - if(!pwd.empty()) - { - dir = pwd.c_str(); - } - else - { - dir = NULL; - } - - // - // Make a copy of the command line. - // - char* cmdbuf = strdup(cmd.c_str()); - - // - // Create the environment block for the child process. We start with the environment - // of this process, and then merge environment variables from the server description. - // - const char* env = NULL; - string envbuf; - if(!server->description.envs.empty()) - { - map<string, string> envMap; - LPVOID parentEnv = GetEnvironmentStrings(); - const char* var = reinterpret_cast<const char*>(parentEnv); - if(*var == '=') - { - // - // The environment block may start with some information about the - // current drive and working directory. This is indicated by a leading - // '=' character, so we skip to the first '\0' byte. - // - while(*var) - var++; - var++; - } - while(*var) - { - string s(var); - string::size_type pos = s.find('='); - if(pos != string::npos) - { - envMap.insert(map<string, string>::value_type(s.substr(0, pos), s.substr(pos + 1))); - } - var += s.size(); - var++; // Skip the '\0' byte - } - FreeEnvironmentStrings(static_cast<char*>(parentEnv)); - for(p = server->description.envs.begin(); p != server->description.envs.end(); ++p) - { - string s = *p; - string::size_type pos = s.find('='); - if(pos != string::npos) - { - envMap.insert(map<string, string>::value_type(s.substr(0, pos), s.substr(pos + 1))); - } - } - for(map<string, string>::const_iterator q = envMap.begin(); q != envMap.end(); ++q) - { - envbuf.append(q->first); - envbuf.push_back('='); - envbuf.append(q->second); - envbuf.push_back('\0'); - } - envbuf.push_back('\0'); - env = envbuf.c_str(); - } - - Process process; - - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - if(_outputDir.size() > 0) - { - string outFile = _outputDir + "/" + server->description.name + ".out"; - - SECURITY_ATTRIBUTES sec = { 0 }; - sec.nLength = sizeof(sec); - sec.bInheritHandle = true; - - process.outHandle = CreateFile(outFile.c_str(), - GENERIC_WRITE, - FILE_SHARE_READ, - &sec, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - if(process.outHandle == INVALID_HANDLE_VALUE) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - // - // NOTE: INVALID_SET_FILE_POINTER is not defined in VC6. - // - //if(SetFilePointer(process.outHandle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) - if(SetFilePointer(process.outHandle, 0, NULL, FILE_END) == (DWORD)-1) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - if(_redirectErrToOut) - { - process.errHandle = process.outHandle; - } - else - { - string errFile = _outputDir + "/" + server->description.name + ".err"; - - process.errHandle = CreateFile(errFile.c_str(), - GENERIC_WRITE, - FILE_SHARE_READ, - &sec, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - if(process.errHandle == INVALID_HANDLE_VALUE) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - // - // NOTE: INVALID_SET_FILE_POINTER is not defined in VC6. - // - //if(SetFilePointer(process.errHandle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) - if(SetFilePointer(process.errHandle, 0, NULL, FILE_END) == (DWORD)-1) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - } - - si.hStdInput = GetStdHandle(STD_OUTPUT_HANDLE); - if(si.hStdInput == INVALID_HANDLE_VALUE) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - si.hStdOutput = process.outHandle; - si.hStdError = process.errHandle; - si.dwFlags = STARTF_USESTDHANDLES; - } - else - { - process.outHandle = GetStdHandle(STD_OUTPUT_HANDLE); - if(process.outHandle == INVALID_HANDLE_VALUE) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - if(_redirectErrToOut) - { - process.errHandle = process.outHandle; - } - else - { - process.errHandle = GetStdHandle(STD_ERROR_HANDLE); - if(process.errHandle == INVALID_HANDLE_VALUE) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - } - } - - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(pi)); - - BOOL b = CreateProcess( - NULL, // Executable - cmdbuf, // Command line - NULL, // Process attributes - NULL, // Thread attributes - TRUE, // Inherit handles - CREATE_NEW_PROCESS_GROUP, // Process creation flags - (LPVOID)env, // Process environment - dir, // Current directory - &si, // Startup info - &pi // Process info - ); - - free(cmdbuf); - - if(!b) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - // - // Caller is responsible for closing handles in PROCESS_INFORMATION. We don't need to - // keep the thread handle, so we close it now. The process handle will be closed later. - // - CloseHandle(pi.hThread); - - process.pid = pi.dwProcessId; - process.hnd = pi.hProcess; - process.server = server; - _processes.push_back(process); - - setInterrupt(); - - if(_traceLevels->activator > 0) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "activated server `" << server->description.name << "' (pid = " << pi.dwProcessId << ")"; - } -#else - int fds[2]; - if(pipe(fds) != 0) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - // - // Convert to standard argc/argv. - // - int argc = static_cast<int>(args.size()); - char** argv = static_cast<char**>(malloc((argc + 1) * sizeof(char*))); - int i = 0; - for(StringSeq::const_iterator p = args.begin(); p != args.end(); ++p, ++i) - { - assert(i < argc); - argv[i] = strdup(p->c_str()); - } - assert(i == argc); - argv[argc] = 0; - - int envCount = server->description.envs.size(); - char** envs = new char*[envCount]; - i = 0; - for(StringSeq::const_iterator q = server->description.envs.begin(); q != server->description.envs.end(); ++q) - { - envs[i++] = strdup(q->c_str()); - } - - // - // stdout and stderr redirection - // - int flags = O_WRONLY | O_APPEND | O_CREAT; - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - - int outFd;; - string outFile; - int errFd; - string errFile; - - if(_outputDir.size() == 0) - { - outFd = STDOUT_FILENO; - errFd = _redirectErrToOut ? outFd : STDERR_FILENO; - } - else - { - outFile = _outputDir + "/" + server->description.name + ".out"; - outFd = open(outFile.c_str(), flags, mode); - if(outFd < 0) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - if(_redirectErrToOut) - { - errFile = outFile; - errFd = outFd; - } - else - { - errFile = _outputDir + "/" + server->description.name + ".err"; - errFd = open(errFile.c_str(), flags, mode); - - if(errFd < 0) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - } - } - - const char* outFileCStr = outFile.c_str(); - const char* errFileCStr = errFile.c_str(); - - // - // Current directory - // - const char* pwdCStr = pwd.c_str(); - - pid_t pid = fork(); - if(pid == -1) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - if(pid == 0) // Child process. - { - // - // Until exec, we can only use async-signal safe functions - // - -#ifdef __linux - // - // Create a process group for this child, to be able to send - // a signal to all the thread-processes with killpg - // - setpgrp(); -#endif - - // - // stdout and stderr redirection - // - if(_outputDir.size() > 0) - { - if(dup2(outFd, STDOUT_FILENO) != STDOUT_FILENO) - { - reportChildError(errno, fds[1], "cannot associate stdout with opened file", outFileCStr); - } - - if(dup2(errFd, STDERR_FILENO) != STDERR_FILENO) - { - reportChildError(errno, fds[1], "cannot associate stderr with opened file", errFileCStr); - } - } - - // - // Close all file descriptors, except for standard input, - // standard output, standard error, 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]) - { - close(fd); - } - } - - for(i = 0; i < envCount; i++) - { - if(putenv(envs[i]) != 0) - { - reportChildError(errno, fds[1], "cannot set environment variable", envs[i]); - } - } - // - // Each env is leaked on purpose ... see man putenv(). - // - delete[] envs; - - // - // Change working directory. - // - if(strlen(pwdCStr) != 0) - { - if(chdir(pwdCStr) == -1) - { - reportChildError(errno, fds[1], "cannot change working directory to", pwdCStr); - } - } - - if(execvp(argv[0], argv) == -1) - { - reportChildError(errno, fds[1], "cannot execute", argv[0]); - } - } - else // Parent process. - { - close(fds[1]); - - for(i = 0; i < envCount; ++i) - { - free(envs[i]); - } - delete[] envs; - - Process process; - process.pid = pid; - process.pipeFd = fds[0]; - process.outFd = outFd; - process.errFd = errFd; - process.server = server; - _processes.push_back(process); - - int flags = fcntl(process.pipeFd, F_GETFL); - flags |= O_NONBLOCK; - fcntl(process.pipeFd, F_SETFL, flags); - - setInterrupt(); - - if(_traceLevels->activator > 0) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "activated server `" << server->description.name << "' (pid = " << pid << ")"; - } - } -#endif - - return true; -} - -void -IcePack::ActivatorI::deactivate(const ServerPtr& server) -{ -#ifdef _WIN32 - Ice::Int pid = server->getPid(); - - if(pid == 0) - { - // - // Server is already deactivated. - // - return; - } -#endif - - // - // Try to shut down the server gracefully using the process proxy. - // - Ice::ProcessPrx process = server->getProcess(); - if(process) - { - if(_traceLevels->activator > 1) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "deactivating `" << server->description.name << "' using process proxy"; - } - try - { - process->shutdown(); - return; - } - catch(const Ice::LocalException& ex) - { - Ice::Warning out(_traceLevels->logger); - out << "exception occurred while deactivating `" << server->description.name - << "' using process proxy:\n" << ex; - } - } - - if(_traceLevels->activator > 1) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "no process proxy, deactivating `" << server->description.name << "' using signal"; - } - -#ifdef _WIN32 - // - // Generate a Ctrl+Break event on the child. - // - if(GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid)) - { - if(_traceLevels->activator > 1) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "sent Ctrl+Break to server `" << server->description.name << "' (pid = " << pid << ")"; - } - } - else - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } -#else - // - // Send a SIGTERM to the process. - // - sendSignal(server, SIGTERM); - -#endif -} - -void -IcePack::ActivatorI::kill(const ServerPtr& server) -{ -#ifdef _WIN32 - Ice::Int pid = server->getPid(); - - if(pid == 0) - { - // - // Server is already deactivated. - // - return; - } - - HANDLE hnd = OpenProcess(PROCESS_TERMINATE, FALSE, pid); - if(hnd == NULL) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - BOOL b = TerminateProcess(hnd, 1); - - CloseHandle(hnd); - - if(!b) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - if(_traceLevels->activator > 1) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "terminating server `" << server->description.name << "' (pid = " << pid << ")"; - } - -#else - sendSignal(server, SIGKILL); -#endif -} - - -void -IcePack::ActivatorI::sendSignal(const ServerPtr& server, const string& signal) -{ - sendSignal(server, stringToSignal(signal)); -} -void -IcePack::ActivatorI::sendSignal(const ServerPtr& server, int signal) -{ -#ifdef _WIN32 - // - // TODO: Win32 implementation? - // - throw BadSignalException(); - -#else - Ice::Int pid = server->getPid(); - - if(pid == 0) - { - // - // Server is already deactivated. - // - return; - } - -#ifdef __linux - // Use process groups on Linux instead of processes - int ret = ::killpg(static_cast<pid_t>(pid), signal); -#else - int ret = ::kill(static_cast<pid_t>(pid), signal); -#endif - if(ret != 0 && getSystemErrno() != ESRCH) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - if(_traceLevels->activator > 1) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "sent " << signalToString(signal) << " to server `" - << server->description.name << "' (pid = " << pid << ")"; - } -#endif -} - -void -IcePack::ActivatorI::writeMessage(const ServerPtr& server, const string& message, Ice::Int fd) -{ - assert(fd == 1 || fd == 2); - - string msg = message + "\n"; - -#ifdef _WIN32 - HANDLE handle = 0; -#else - int actualFd = -1; -#endif - { - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - - for(vector<Process>::iterator p = _processes.begin(); p != _processes.end(); ++p) - { - if(p->server == server) - { -#ifdef _WIN32 - handle = (fd == 1 ? p->outHandle : p->errHandle); -#else - actualFd = (fd == 1 ? p->outFd : p->errFd); -#endif - break; // for - } - } - } - -#ifdef _WIN32 - if(handle != 0) - { - DWORD written = 0; - if(!WriteFile(handle, msg.c_str(), msg.size(), &written, NULL)) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - assert(written == msg.size()); - } -#else - if(actualFd > 0) - { - ssize_t written = write(actualFd, msg.c_str(), msg.size()); - if(written == -1) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - assert(written == static_cast<ssize_t>(msg.size())); - } -#endif -} - - -Ice::Int -IcePack::ActivatorI::getServerPid(const ServerPtr& server) -{ - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - - for(vector<Process>::iterator p = _processes.begin(); p != _processes.end(); ++p) - { - if(p->server == server) - { - return static_cast<Ice::Int>(p->pid); - } - } - - return 0; -} - -void -IcePack::ActivatorI::start() -{ - // - // Create and start the termination listener thread. - // - _thread = new TerminationListenerThread(*this); - _thread->start(); -} - -void -IcePack::ActivatorI::waitForShutdown() -{ - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - while(!_deactivating) - { - wait(); - } -} - -void -IcePack::ActivatorI::shutdown() -{ - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - // - // Deactivation has been initiated. Set _deactivating to true to - // prevent activation of new processes. This will also cause the - // termination listener thread to stop when there are no more - // active processes. - // - _deactivating = true; - setInterrupt(); - notifyAll(); -} - -void -IcePack::ActivatorI::destroy() -{ - { - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - assert(_deactivating); - } - - // - // Deactivate all the processes. - // - deactivateAll(); - - // - // Join the termination listener thread. This thread terminates - // when there's no more processes and when _deactivating is set to - // true. - // - _thread->getThreadControl().join(); - _thread = 0; -} - -void -IcePack::ActivatorI::runTerminationListener() -{ - try - { - terminationListener(); - } - catch(const Exception& ex) - { - Error out(_traceLevels->logger); - out << "exception in process termination listener:\n" << ex; - } - catch(...) - { - Error out(_traceLevels->logger); - out << "unknown exception in process termination listener"; - } -} - -void -IcePack::ActivatorI::deactivateAll() -{ - // - // Stop all active processes. - // - vector<Process> processes; - { - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - processes = _processes; - } - - for(vector<Process>::iterator p = processes.begin(); p != processes.end(); ++p) - { - // - // Stop the server. The listener thread should detect the - // process deactivation and remove it from the activator's - // list of active processes. - // - try - { - p->server->stop(); - } - catch(const ObjectNotExistException&) - { - // - // Expected if the server was in the process of being destroyed. - // - } - } -} - -void -IcePack::ActivatorI::terminationListener() -{ -#ifdef _WIN32 - while(true) - { - vector<HANDLE> handles; - - // - // Lock while we collect the process handles. - // - { - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - - for(vector<Process>::iterator p = _processes.begin(); p != _processes.end(); ++p) - { - handles.push_back(p->hnd); - } - } - - handles.push_back(_hIntr); - - // - // Wait for a child to terminate, or the interrupt event to be signaled. - // - DWORD ret = WaitForMultipleObjects(handles.size(), &handles[0], FALSE, INFINITE); - if(ret == WAIT_FAILED) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - vector<HANDLE>::size_type pos = ret - WAIT_OBJECT_0; - assert(pos < handles.size()); - HANDLE hnd = handles[pos]; - - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - - if(hnd == _hIntr) - { - clearInterrupt(); - } - else - { - for(vector<Process>::iterator p = _processes.begin(); p != _processes.end(); ++p) - { - if(p->hnd == hnd) - { - if(_traceLevels->activator > 0) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "detected termination of server `" << p->server->description.name << "'"; - } - - try - { - p->server->terminated(); - } - catch(const Ice::LocalException& ex) - { - Ice::Warning out(_traceLevels->logger); - out << "unexpected exception raised by server `" << p->server->description.name - << "' termination:\n" << ex; - } - - CloseHandle(hnd); - if(_outputDir.size() > 0) - { - // - // STDOUT and STDERR should not be closed - // - CloseHandle(p->outHandle); - if(!_redirectErrToOut) - { - CloseHandle(p->errHandle); - } - } - _processes.erase(p); - break; - } - } - - } - - if(_deactivating && _processes.empty()) - { - return; - } - } -#else - while(true) - { - fd_set fdSet; - int maxFd = _fdIntrRead; - FD_ZERO(&fdSet); - FD_SET(_fdIntrRead, &fdSet); - - { - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - - for(vector<Process>::iterator p = _processes.begin(); p != _processes.end(); ++p) - { - int fd = p->pipeFd; - FD_SET(fd, &fdSet); - if(maxFd < fd) - { - maxFd = fd; - } - } - } - - repeatSelect: - int ret = ::select(maxFd + 1, &fdSet, 0, 0, 0); - assert(ret != 0); - - if(ret == -1) - { -#ifdef EPROTO - if(errno == EINTR || errno == EPROTO) - { - goto repeatSelect; - } -#else - if(errno == EINTR) - { - goto repeatSelect; - } -#endif - - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - { - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - - if(FD_ISSET(_fdIntrRead, &fdSet)) - { - clearInterrupt(); - - if(_deactivating && _processes.empty()) - { - return; - } - } - - vector<Process>::iterator p = _processes.begin(); - while(p != _processes.end()) - { - int fd = p->pipeFd; - if(!FD_ISSET(fd, &fdSet)) - { - ++p; - continue; - } - - char s[16]; - ssize_t rs; - string message; - - // - // Read the message over the pipe. - // - while((rs = read(fd, &s, 16)) > 0) - { - message.append(s, rs); - } - - if(rs == -1) - { - if(errno != EAGAIN || message.empty()) - { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } - - ++p; - } - else if(rs == 0) - { - // - // If the pipe was closed, the process has terminated. - // - - if(_traceLevels->activator > 0) - { - Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); - out << "detected termination of server `" << p->server->description.name << "'"; - } - - try - { - p->server->terminated(); - } - catch(const Ice::LocalException& ex) - { - Ice::Warning out(_traceLevels->logger); - out << "unexpected exception raised by server `" << p->server->description.name - << "' termination:\n" << ex; - } - - if(p->errFd != p->outFd && p->errFd != STDERR_FILENO) - { - close(p->errFd); - } - if(p->outFd != STDOUT_FILENO) - { - close(p->outFd); - } - close(p->pipeFd); - p = _processes.erase(p); - - // - // We are deactivating and there's no more active processes. We can now - // end this loop - // - if(_deactivating && _processes.empty()) - { - return; - } - } - - // - // Log the received message. - // - if(!message.empty()) - { - Error out(_traceLevels->logger); - out << message; - } - } - } - } -#endif -} - -void -IcePack::ActivatorI::clearInterrupt() -{ -#ifdef _WIN32 - ResetEvent(_hIntr); -#else - char c; - while(read(_fdIntrRead, &c, 1) == 1) - ; -#endif -} - -void -IcePack::ActivatorI::setInterrupt() -{ -#ifdef _WIN32 - SetEvent(_hIntr); -#else - char c = 0; - write(_fdIntrWrite, &c, 1); -#endif -} |