diff options
Diffstat (limited to 'nxcomp/Proxy.cpp')
-rw-r--r-- | nxcomp/Proxy.cpp | 183 |
1 files changed, 150 insertions, 33 deletions
diff --git a/nxcomp/Proxy.cpp b/nxcomp/Proxy.cpp index e499b443e..123181489 100644 --- a/nxcomp/Proxy.cpp +++ b/nxcomp/Proxy.cpp @@ -29,6 +29,8 @@ #include <string.h> #include <sys/types.h> #include <sys/stat.h> +#include <signal.h> + #ifdef ANDROID #include <netinet/in.h> #include <netinet/ip.h> @@ -92,6 +94,8 @@ struct sockaddr_un extern void CleanupListeners(); +extern int HandleChild(int); + // // Default size of string buffers. // @@ -165,6 +169,7 @@ Proxy::Proxy(int fd) fdMap_[channelId] = nothing; channelMap_[channelId] = nothing; + slavePidMap_[channelId] = nothing; } inputChannel_ = nothing; @@ -296,6 +301,66 @@ Proxy::~Proxy() } } + // + // Kill all active slave channel children, and + // give them 5 seconds to exit nicely. + + #ifdef DEBUG + *logofs << "Proxy: Killing active slaves" << endl; + #endif + + int slave_count = 999; + int loop_count = 0; + + while(slave_count > 0 && loop_count < 50) + { + slave_count = 0; + + for (int channelId = 0; channelId<CONNECTIONS_LIMIT; channelId++) + { + int pid = slavePidMap_[channelId]; + + if (pid > 1) { + slave_count++; + + #ifdef DEBUG + *logofs << "Proxy: Active slave with pid " << pid << logofs_flush; + #endif + + if ( loop_count == 0 ) + { + #ifdef DEBUG + *logofs << "Proxy: Sending SIGTERM to " << pid << logofs_flush; + #endif + kill(pid, SIGTERM); + } + else if ( loop_count == 25 ) + { + #ifdef DEBUG + *logofs << "Proxy: Sending SIGKILL to " << pid << logofs_flush; + #endif + kill(pid, SIGKILL); + } + + if (HandleChild(pid)) + { + #ifdef DEBUG + *logofs << "Proxy: Slave " << pid << " terminated" << logofs_flush; + #endif + slavePidMap_[channelId] = nothing; + } + } + } + + if ( slave_count > 0 ) + { + cerr << "Proxy: Error: Failed to kill all slave channel processes. " << slave_count << " processes still remaining." << endl; + } + + usleep(200000); + loop_count++; + } + delete transport_; delete compressor_; @@ -6308,42 +6373,94 @@ int Proxy::handleNewGenericConnectionFromProxyUnix(int channelId, T_channel_type int Proxy::handleNewSlaveConnectionFromProxy(int channelId) { - // - // Implementation is incomplete. Opening a - // slave channel should let the proxy fork - // a new client and pass to it the channel - // descriptors. For now we make the channel - // fail immediately. - // - // #include <fcntl.h> - // #include <sys/types.h> - // #include <sys/stat.h> - // - // char *slaveServer = "/dev/null"; - // - // #ifdef TEST - // *logofs << "Proxy: Opening file '" << slaveServer - // << "'.\n" << logofs_flush; - // #endif - // - // int serverFd = open(slaveServer, O_RDWR); - // - // if (handlePostConnectionFromProxy(channelId, serverFd, channel_slave, "slave") < 0) - // { - // return -1; - // } - // - #ifdef WARNING - *logofs << "Proxy: Refusing new slave connection for " - << "channel ID#" << channelId << "\n" - << logofs_flush; - #endif + cerr << "Info" << ": New slave connection on " + << "channel ID#" << channelId << "\n"; + + char *nx_slave_cmd = getenv("NX_SLAVE_CMD"); + if (nx_slave_cmd == NULL) { + return -1; + } - cerr << "Warning" << ": Refusing new slave connection for " - << "channel ID#" << channelId << "\n"; + int spair[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, spair) == -1) { + perror("socketpair"); + return -1; + } - return -1; + int serverFd = spair[0]; + int clientFd = spair[1]; + + if (handlePostConnectionFromProxy(channelId, serverFd, channel_slave, "slave") < 0) + { + close(serverFd); + close(clientFd); + return -1; + } + + + int pid = fork(); + if (pid == 0) + { + + if (dup2(clientFd, 0) == -1) + { + perror("dup2"); + exit(1); + } + + if (dup2(clientFd, 1) == -1) + { + perror("dup2"); + exit(1); + } + + close(serverFd); + close(clientFd); + + /* Close FDs used by NX, QVD #1208 */ + for (int fd = 3; fd < 256; fd++) { + close(fd); + } + + char *const argv[2] = {nx_slave_cmd, NULL}; + + if (execv(nx_slave_cmd, argv) == -1) + { + perror("execv"); + } + exit(1); + + } + else if (pid == -1) + { + // TODO Test this! + perror("fork"); + close(serverFd); + close(clientFd); + return -1; + } + + close(clientFd); + slavePidMap_[channelId] = pid; + + cerr << "Info" << ": slave channel ID#" << channelId << " handler has PID " << pid << endl; + + return 1; +} + +void Proxy::checkSlaves() +{ + for (int channelId = 0; channelId<CONNECTIONS_LIMIT; channelId++) + { + int pid = slavePidMap_[channelId]; + + if (pid > 1 && HandleChild(pid)) + { + slavePidMap_[channelId] = nothing; + cerr << "Info:" << " Handled death of slave with pid " << pid << endl; + } + } } int Proxy::handlePostConnectionFromProxy(int channelId, int serverFd, |