diff options
Diffstat (limited to 'cpp/src/Ice/Service.cpp')
-rwxr-xr-x | cpp/src/Ice/Service.cpp | 135 |
1 files changed, 98 insertions, 37 deletions
diff --git a/cpp/src/Ice/Service.cpp b/cpp/src/Ice/Service.cpp index 8f2a55aea90..d7edd280df9 100755 --- a/cpp/src/Ice/Service.cpp +++ b/cpp/src/Ice/Service.cpp @@ -281,13 +281,13 @@ Ice::Service::syserror(const std::string& msg) (LPTSTR)&lpMsgBuf, 0, NULL); - if(ok) - { + if(ok) + { LPCTSTR str = (LPCTSTR)lpMsgBuf; assert(str && strlen((const char*)str) > 0); errmsg = (const char*)str; LocalFree(lpMsgBuf); - } + } } #else int err = errno; @@ -1112,6 +1112,8 @@ Ice::Service::checkDaemon(int argc, char* argv[], int& status) // Check for --daemon. // bool daemonize = false; + bool noClose = false; + bool noChdir = false; int idx = 1; while(idx < argc) { @@ -1125,12 +1127,46 @@ Ice::Service::checkDaemon(int argc, char* argv[], int& status) daemonize = true; } + else if(strcmp(argv[idx], "--noclose") == 0) + { + for(int i = idx; i + 1 < argc; ++i) + { + argv[i] = argv[i + 1]; + } + argc -= 1; + + noClose = true; + } + else if(strcmp(argv[idx], "--nochdir") == 0) + { + for(int i = idx; i + 1 < argc; ++i) + { + argv[i] = argv[i + 1]; + } + argc -= 1; + + noChdir = true; + } else { ++idx; } } + if(noClose && !daemonize) + { + cerr << argv[0] << ": --noclose must be used with --daemon" << endl; + status = EXIT_FAILURE; + return true; + } + + if(noChdir && !daemonize) + { + cerr << argv[0] << ": --nochdir must be used with --daemon" << endl; + status = EXIT_FAILURE; + return true; + } + if(!daemonize) { return false; @@ -1227,14 +1263,17 @@ Ice::Service::checkDaemon(int argc, char* argv[], int& status) // umask(0); - // - // Change the working directory. - // - if(chdir("/") != 0) + if(!noChdir) { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; + // + // Change the working directory. + // + if(chdir("/") != 0) + { + SyscallException ex(__FILE__, __LINE__); + ex.error = getSystemErrno(); + throw ex; + } } // @@ -1247,42 +1286,39 @@ Ice::Service::checkDaemon(int argc, char* argv[], int& status) throw ex; } - // - // Close open file descriptors. - // - int fdMax = sysconf(_SC_OPEN_MAX); - if(fdMax <= 0) + fd_set fdsToClose; + int fdMax; + if(!noClose) { - SyscallException ex(__FILE__, __LINE__); - ex.error = getSystemErrno(); - throw ex; - } + // + // Take a snapshot of the open file descriptors. We don't actually close these + // descriptors until after the communicator is initialized, so that plug-ins + // have an opportunity to use stdin/stdout/stderr if necessary. + // + FD_ZERO(&fdsToClose); + fdMax = sysconf(_SC_OPEN_MAX); + if(fdMax <= 0) + { + SyscallException ex(__FILE__, __LINE__); + ex.error = getSystemErrno(); + throw ex; + } - int i; - for(i = 0; i < fdMax; ++i) - { - if(i != fds[1]) + for(int i = 0; i < fdMax; ++i) { - close(i); + if(fcntl(i, F_GETFL) != -1) + { + FD_SET(i, &fdsToClose); + } } + FD_CLR(fds[1], &fdsToClose); // Don't close the write end of the pipe. } // - // Associate stdin, stdout and stderr with /dev/null. - // - int fd; - fd = open("/dev/null", O_RDWR); - assert(fd == 0); - fd = dup2(0, 1); - assert(fd == 1); - fd = dup2(1, 2); - assert(fd == 2); - - // // Create the CtrlCHandler after forking the child so that signals // are initialized properly. We do this before initializing the - // communicator because we need to ensure that this is done before any - // additional threads are created. + // communicator because we need to ensure that signals are initialized + // before additional threads are created. // _ctrlCHandler = new IceUtil::CtrlCHandler; @@ -1291,6 +1327,31 @@ Ice::Service::checkDaemon(int argc, char* argv[], int& status) // initializeCommunicator(argc, argv); + if(!noClose) + { + // + // Close unnecessary file descriptors. + // + for(int i = 0; i < fdMax; ++i) + { + if(FD_ISSET(i, &fdsToClose)) + { + close(i); + } + } + + // + // Associate stdin, stdout and stderr with /dev/null. + // + int fd; + fd = open("/dev/null", O_RDWR); + assert(fd == 0); + fd = dup2(0, 1); + assert(fd == 1); + fd = dup2(1, 2); + assert(fd == 2); + } + // // Use the configured logger. // |