Fixes and new functionality by Wouter Spruit, mostly for the HTTP proxy rewrite.
This commit is contained in:
		
							parent
							
								
									d3bb5b13e4
								
							
						
					
					
						commit
						57bcd8f25c
					
				
					 5 changed files with 72 additions and 26 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<pid_t, std::string>(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_t, std::string>(pid, name));
 | 
			
		||||
  }
 | 
			
		||||
  return pid;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue