it works perfectly with blocking pipes and buffer size of 1
This commit is contained in:
		
							
								
								
									
										26
									
								
								mrw/exec.cpp
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								mrw/exec.cpp
									
									
									
									
									
								
							@@ -9,6 +9,9 @@
 | 
			
		||||
    @license LGPL, see file <a href="license.html">COPYING</a>
 | 
			
		||||
 | 
			
		||||
    $Log$
 | 
			
		||||
    Revision 1.7  2004/12/17 17:38:57  marc
 | 
			
		||||
    it works perfectly with blocking pipes and buffer size of 1
 | 
			
		||||
 | 
			
		||||
    Revision 1.6  2004/12/17 16:28:51  marc
 | 
			
		||||
    stable implementation with select for both executes
 | 
			
		||||
 | 
			
		||||
@@ -38,6 +41,7 @@
 | 
			
		||||
#include <string.h>  // memcpy
 | 
			
		||||
#include <assert.h> // assert
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
mrw::ExecutionFailedExc::ExecutionFailedExc(const std::string& w,
 | 
			
		||||
                                            const std::string& c)
 | 
			
		||||
  throw(std::bad_exception):
 | 
			
		||||
@@ -129,7 +133,7 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
 | 
			
		||||
      program. */
 | 
			
		||||
  _success = false;
 | 
			
		||||
  _res = _err = "";
 | 
			
		||||
  mrw::Pipe stdOut, stdErr;
 | 
			
		||||
  mrw::Pipe stdOut(true), stdErr(true);
 | 
			
		||||
  if (!stdOut || !stdErr)
 | 
			
		||||
    throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd);
 | 
			
		||||
  pid_t pid(fork());
 | 
			
		||||
@@ -142,8 +146,12 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
 | 
			
		||||
      throw ExecutionFailedExc("cannot close pipe", *_cmd);
 | 
			
		||||
    ssize_t num1(-1), num2(-1);
 | 
			
		||||
    fd_set readfds;
 | 
			
		||||
    char buf[4096];
 | 
			
		||||
    char buf[1]; // used to have larger buffer, but since non blocking fails...
 | 
			
		||||
    int res(0), s(0);
 | 
			
		||||
    /** @bug It sometimes did not get the whole input since I
 | 
			
		||||
             changed to non blocking pipes. Now pipes are blocking
 | 
			
		||||
             again and buffer size is 1, so I hope all problems are
 | 
			
		||||
             resolved. Please report any problems! */
 | 
			
		||||
    while (num1||num2) try { // not all end of file
 | 
			
		||||
      if (!res && (res=waitpid(pid, &s, WNOHANG)))
 | 
			
		||||
        if (res!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0)
 | 
			
		||||
@@ -155,7 +163,7 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
 | 
			
		||||
      int n(mrw::max((num1?stdOut.istream():0),
 | 
			
		||||
                     (num2?stdErr.istream():0)));
 | 
			
		||||
      timeval tm = {0, 10000};
 | 
			
		||||
      int num = select(n, &readfds, 0, 0, &tm);
 | 
			
		||||
      int num = select(n+1, &readfds, 0, 0, 0);
 | 
			
		||||
      if (num<0) throw ExecutionFailedExc("select failed", *_cmd);
 | 
			
		||||
      if (num==0 && res==pid) break; // process ended, no data left
 | 
			
		||||
      // check and handle stdout
 | 
			
		||||
@@ -175,6 +183,7 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
 | 
			
		||||
      _success = false;
 | 
			
		||||
      return *this;
 | 
			
		||||
    }
 | 
			
		||||
    std::cout<<"num1="<<num1<<", num2="<<num2<<std::endl;
 | 
			
		||||
  } else { // child
 | 
			
		||||
    stdOut.close_in();
 | 
			
		||||
    stdErr.close_in();
 | 
			
		||||
@@ -201,7 +210,7 @@ mrw::Exec& mrw::Exec::execute(const std::string& input, bool exc)
 | 
			
		||||
  _success = false;
 | 
			
		||||
  _res = _err = "";
 | 
			
		||||
  mrw::Pipe stdIn(true), // child terminates if stdin is non-blocking
 | 
			
		||||
     stdOut, stdErr;
 | 
			
		||||
    stdOut(true), stdErr(true); // non blocking is also a problem here
 | 
			
		||||
  if (!stdIn || !stdOut || !stdErr)
 | 
			
		||||
    throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd);
 | 
			
		||||
  pid_t pid(fork());
 | 
			
		||||
@@ -215,8 +224,12 @@ mrw::Exec& mrw::Exec::execute(const std::string& input, bool exc)
 | 
			
		||||
    ssize_t num0(-1), num1(-1), num2(-1);
 | 
			
		||||
    std::string in(input);
 | 
			
		||||
    fd_set writefds, readfds;
 | 
			
		||||
    char buf[4096];
 | 
			
		||||
    char buf[1]; // used to have larger buffer, but since non blocking fails...
 | 
			
		||||
    int res(0), s(0);
 | 
			
		||||
    /** @bug It sometimes did not get the whole input since I
 | 
			
		||||
             changed to non blocking pipes. Now pipes are blocking
 | 
			
		||||
             again and buffer size is 1, so I hope all problems are
 | 
			
		||||
             resolved. Please report any problems! */
 | 
			
		||||
    while (num0||num1||num2) try { // not all end of file
 | 
			
		||||
      if (!res && (res=waitpid(pid, &s, WNOHANG)))
 | 
			
		||||
        if (res!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0)
 | 
			
		||||
@@ -231,7 +244,7 @@ mrw::Exec& mrw::Exec::execute(const std::string& input, bool exc)
 | 
			
		||||
                     mrw::max((num1?stdOut.istream():0),
 | 
			
		||||
                              (num2?stdErr.istream():0))));
 | 
			
		||||
      timeval tm = {0, 10000};
 | 
			
		||||
      int num = select(n, &readfds, &writefds, 0, &tm);
 | 
			
		||||
      int num = select(n+1, &readfds, &writefds, 0, &tm);
 | 
			
		||||
      if (num<0) throw ExecutionFailedExc("select failed", *_cmd);
 | 
			
		||||
      if (num==0 && res==pid) break; // process ended, no data left
 | 
			
		||||
      // check and handle stdin
 | 
			
		||||
@@ -261,6 +274,7 @@ mrw::Exec& mrw::Exec::execute(const std::string& input, bool exc)
 | 
			
		||||
      _success = false;
 | 
			
		||||
      return *this;
 | 
			
		||||
    }
 | 
			
		||||
    std::cout<<"num0="<<num0<<", num1="<<num1<<", num2="<<num2<<std::endl;
 | 
			
		||||
  } else { // child
 | 
			
		||||
    stdIn.close_out();
 | 
			
		||||
    stdOut.close_in();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user