From 57bcd8f25cc34d85c6b1a892e3b1135028a42b34 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Wed, 18 Jun 2014 10:38:40 +0200 Subject: [PATCH] Fixes and new functionality by Wouter Spruit, mostly for the HTTP proxy rewrite. --- lib/config.cpp | 19 ++++++++++++++++--- lib/procs.cpp | 47 ++++++++++++++++++++++++++++++++++------------- lib/procs.h | 3 +++ lib/socket.cpp | 24 ++++++++++++++++-------- lib/socket.h | 5 +++-- 5 files changed, 72 insertions(+), 26 deletions(-) diff --git a/lib/config.cpp b/lib/config.cpp index d341f3aa..514286b4 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -428,6 +428,7 @@ void Util::Config::activate(){ } } struct sigaction new_action; + struct sigaction cur_action; new_action.sa_handler = signal_handler; sigemptyset( &new_action.sa_mask); new_action.sa_flags = 0; @@ -435,7 +436,11 @@ void Util::Config::activate(){ sigaction(SIGHUP, &new_action, NULL); sigaction(SIGTERM, &new_action, NULL); sigaction(SIGPIPE, &new_action, NULL); - sigaction(SIGCHLD, &new_action, NULL); + //check if a child signal handler isn't set already, if so, set it. + sigaction(SIGCHLD, 0, &cur_action); + if (cur_action.sa_handler == SIG_DFL || cur_action.sa_handler == SIG_IGN){ + sigaction(SIGCHLD, &new_action, NULL); + } is_active = true; } @@ -449,9 +454,17 @@ void Util::Config::signal_handler(int signum){ case SIGTERM: is_active = false; break; - case SIGCHLD: //when a child dies, reap it. - wait(0); + case SIGCHLD:{ //when a child dies, reap it. + int status; + pid_t ret = -1; + while (ret != 0){ + ret = waitpid( -1, &status, WNOHANG); + if (ret < 0 && errno != EINTR){ + break; + } + } break; + } default: //other signals are ignored break; } diff --git a/lib/procs.cpp b/lib/procs.cpp index ceb4dbf5..b0dd0281 100644 --- a/lib/procs.cpp +++ b/lib/procs.cpp @@ -126,12 +126,16 @@ void Util::Procs::setHandler(){ sigaction(SIGCHLD, &new_action, NULL); atexit(exit_handler); handler_set = true; - } + }// else { + // DEBUG_MSG(DLVL_DEVEL, "not setting handler"); + // } } + /// Used internally to capture child signals and update plist. void Util::Procs::childsig_handler(int signum){ if (signum != SIGCHLD){ + DEBUG_MSG(DLVL_DEVEL, "signum != SIGCHLD"); return; } int status; @@ -142,13 +146,14 @@ void Util::Procs::childsig_handler(int signum){ if (ret == 0 || errno != EINTR){ return; } + continue; } int exitcode; if (WIFEXITED(status)){ exitcode = WEXITSTATUS(status); }else if (WIFSIGNALED(status)){ exitcode = -WTERMSIG(status); - }else{/* not possible */ + }else{// not possible return; } @@ -186,6 +191,7 @@ std::string Util::Procs::getOutputOf(char* const* argv){ ret += fileBuf; } fclose(outFile); + free(fileBuf); return ret; } @@ -201,6 +207,7 @@ std::string Util::Procs::getOutputOf(std::string cmd){ while ( !(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){ ret += fileBuf; } + free(fileBuf); fclose(outFile); return ret; } @@ -431,15 +438,24 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i DEBUG_MSG(DLVL_WARN, "Process %s already active - skipping start", name.c_str()); return getPid(name); } + int pidtemp = StartPiped(argv, fdin, fdout, fderr); + if (pidtemp > 0 ) { + plist.insert(std::pair(pidtemp, name)); + } + return pidtemp; +} + +pid_t Util::Procs::StartPiped(char* const* argv, int * fdin, int * fdout, int * fderr){ pid_t pid; int pipein[2], pipeout[2], pipeerr[2]; + //DEBUG_MSG(DLVL_DEVEL, "setHandler"); setHandler(); if (fdin && *fdin == -1 && pipe(pipein) < 0){ - DEBUG_MSG(DLVL_ERROR, "Pipe in creation failed for process %s", name.c_str()); + DEBUG_MSG(DLVL_ERROR, "Pipe in creation failed for process %s", argv[0]); return 0; } if (fdout && *fdout == -1 && pipe(pipeout) < 0){ - DEBUG_MSG(DLVL_ERROR, "Pipe out creation failed for process %s", name.c_str()); + DEBUG_MSG(DLVL_ERROR, "Pipe out creation failed for process %s", argv[0]); if ( *fdin == -1){ close(pipein[0]); close(pipein[1]); @@ -447,7 +463,7 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i return 0; } if (fderr && *fderr == -1 && pipe(pipeerr) < 0){ - DEBUG_MSG(DLVL_ERROR, "Pipe err creation failed for process %s", name.c_str()); + DEBUG_MSG(DLVL_ERROR, "Pipe err creation failed for process %s", argv[0]); if ( *fdin == -1){ close(pipein[0]); close(pipein[1]); @@ -462,7 +478,7 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i if ( !fdin || !fdout || !fderr){ devnull = open("/dev/null", O_RDWR); if (devnull == -1){ - DEBUG_MSG(DLVL_ERROR, "Could not open /dev/null for process %s: %s", name.c_str(), strerror(errno)); + DEBUG_MSG(DLVL_ERROR, "Could not open /dev/null for process %s: %s", argv[0], strerror(errno)); if ( *fdin == -1){ close(pipein[0]); close(pipein[1]); @@ -488,7 +504,6 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i close(pipein[0]); }else if ( *fdin != STDIN_FILENO){ dup2( *fdin, STDIN_FILENO); - close( *fdin); } if ( !fdout){ dup2(devnull, STDOUT_FILENO); @@ -497,8 +512,7 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i dup2(pipeout[1], STDOUT_FILENO); close(pipeout[1]); }else if ( *fdout != STDOUT_FILENO){ - dup2( *fdout, STDOUT_FILENO); - close( *fdout); + dup2( *fdout, STDOUT_FILENO); } if ( !fderr){ dup2(devnull, STDERR_FILENO); @@ -508,16 +522,24 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i close(pipeerr[1]); }else if ( *fderr != STDERR_FILENO){ dup2( *fderr, STDERR_FILENO); + } + if( fdin && *fdin !=-1 && *fdin != STDIN_FILENO){ + close( *fdin); + } + if( fdout && *fdout !=-1 && *fdout != STDOUT_FILENO){ + close( *fdout); + } + if( fderr && *fderr !=-1 && *fderr != STDERR_FILENO){ close( *fderr); } if (devnull != -1){ close(devnull); } execvp(argv[0], argv); - DEBUG_MSG(DLVL_ERROR, "execvp() failed for process %s", name.c_str()); + DEBUG_MSG(DLVL_ERROR, "execvp() failed for process %s", argv[0]); exit(42); }else if (pid == -1){ - DEBUG_MSG(DLVL_ERROR, "fork() for pipe failed for process %s", name.c_str()); + DEBUG_MSG(DLVL_ERROR, "fork() for pipe failed for process %s", argv[0]); if (fdin && *fdin == -1){ close(pipein[0]); close(pipein[1]); @@ -535,7 +557,7 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i } return 0; }else{ //parent - DEBUG_MSG(DLVL_HIGH, "Piped process %s started, PID %d: %s", name.c_str(), pid, argv[0]); + DEBUG_MSG(DLVL_HIGH, "Piped process %s started, PID %d", argv[0], pid); if (devnull != -1){ close(devnull); } @@ -551,7 +573,6 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i close(pipeerr[1]); // close unused write end *fderr = pipeerr[0]; } - plist.insert(std::pair(pid, name)); } return pid; } diff --git a/lib/procs.h b/lib/procs.h index 8df712fc..10cd04da 100644 --- a/lib/procs.h +++ b/lib/procs.h @@ -28,7 +28,10 @@ namespace Util { static pid_t Start(std::string name, std::string cmd); static pid_t Start(std::string name, std::string cmd, std::string cmd2); static pid_t Start(std::string name, std::string cmd, std::string cmd2, std::string cmd3); + + static pid_t StartPiped(char* const* argv, int * fdin, int * fdout, int * fderr); static pid_t StartPiped(std::string name, char* const* argv, int * fdin, int * fdout, int * fderr); + static pid_t StartPiped(std::string name, std::string cmd, int * fdin, int * fdout, int * fderr); static pid_t StartPiped2(std::string name, std::string cmd1, std::string cmd2, int * fdin, int * fdout, int * fderr1, int * fderr2); static void Stop(std::string name); diff --git a/lib/socket.cpp b/lib/socket.cpp index 51687220..baac5b79 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -427,6 +427,13 @@ bool Socket::Connection::spool(){ } } +/// +bool Socket::Connection::peek(){ + /// clear buffer + downbuffer.clear(); + return iread(downbuffer, MSG_PEEK); +} + /// Updates the downbuffer and upbuffer internal variables until upbuffer is empty. /// Returns true if new data was received, false otherwise. bool Socket::Connection::flush(){ @@ -563,15 +570,16 @@ unsigned int Socket::Connection::iwrite(const void * buffer, int len){ /// \param buffer Location of the buffer to read to. /// \param len Amount of bytes to read. /// \returns The amount of bytes actually read. -int Socket::Connection::iread(void * buffer, int len){ +int Socket::Connection::iread(void * buffer, int len, int flags){ if ( !connected() || len < 1){ return 0; } int r; - if (sock >= 0){ - r = recv(sock, buffer, len, 0); - }else{ - r = read(pipes[1], buffer, len); + if (sock >=0 ){ + r = recv(sock, buffer, len, flags); + } else { + //(pipes[1] >=0) { + r = read(pipes[1], buffer, len); } if (r < 0){ switch (errno){ @@ -589,7 +597,7 @@ int Socket::Connection::iread(void * buffer, int len){ break; } } - if (r == 0 && (sock >= 0)){ + if (r == 0){ close(); } down += r; @@ -601,9 +609,9 @@ int Socket::Connection::iread(void * buffer, int len){ /// then appended to end of buffer. /// \param buffer Socket::Buffer to append data to. /// \return True if new data arrived, false otherwise. -bool Socket::Connection::iread(Buffer & buffer){ +bool Socket::Connection::iread(Buffer & buffer, int flags){ char cbuffer[BUFFER_BLOCKSIZE]; - int num = iread(cbuffer, BUFFER_BLOCKSIZE); + int num = iread(cbuffer, BUFFER_BLOCKSIZE, flags); if (num < 1){ return false; } diff --git a/lib/socket.h b/lib/socket.h index 172009ce..4f046156 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -54,9 +54,9 @@ namespace Socket { long long int conntime; Buffer downbuffer; ///< Stores temporary data coming in. Buffer upbuffer; ///< Stores temporary data going out. - int iread(void * buffer, int len); ///< Incremental read call. + int iread(void * buffer, int len, int flags = 0); ///< Incremental read call. unsigned int iwrite(const void * buffer, int len); ///< Incremental write call. - bool iread(Buffer & buffer); ///< Incremental write call that is compatible with Socket::Buffer. + bool iread(Buffer & buffer, int flags = 0); ///< Incremental write call that is compatible with Socket::Buffer. bool iwrite(std::string & buffer); ///< Write call that is compatible with std::string. public: //friends @@ -81,6 +81,7 @@ namespace Socket { //buffered i/o methods bool spool(); ///< Updates the downbuffer and upbuffer internal variables. bool flush(); ///< Updates the downbuffer and upbuffer internal variables until upbuffer is empty. + bool peek(); ///< Clears the downbuffer and fills it with peek Buffer & Received(); ///< Returns a reference to the download buffer. void Send(std::string & data); ///< Appends data to the upbuffer. void Send(const char * data); ///< Appends data to the upbuffer.