diff --git a/mrw/exec.cpp b/mrw/exec.cpp
index a51cf83..4794fe6 100644
--- a/mrw/exec.cpp
+++ b/mrw/exec.cpp
@@ -9,6 +9,9 @@
@license LGPL, see file COPYING
$Log$
+ Revision 1.8 2004/12/18 21:00:09 marc
+ everything is ok, when pipes are non blocking on parent's side and blocking on client's side, and select is not used (not necessary for non blocking IO)
+
Revision 1.7 2004/12/17 17:38:57 marc
it works perfectly with blocking pipes and buffer size of 1
@@ -36,12 +39,10 @@
#include
#include
#include // max
-#include // waitpid
-#include // fork, exec
-#include // memcpy
+#include // waitpid#include // fork, exec
+#include // memcpy
#include // assert
-#include
mrw::ExecutionFailedExc::ExecutionFailedExc(const std::string& w,
const std::string& c)
throw(std::bad_exception):
@@ -133,7 +134,7 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
program. */
_success = false;
_res = _err = "";
- mrw::Pipe stdOut(true), stdErr(true);
+ mrw::Pipe stdOut(mrw::Pipe::block_output), stdErr(mrw::Pipe::block_output);
if (!stdOut || !stdErr)
throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd);
pid_t pid(fork());
@@ -144,46 +145,34 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
stdErr.close_out();
if (!stdOut || !stdErr)
throw ExecutionFailedExc("cannot close pipe", *_cmd);
- ssize_t num1(-1), num2(-1);
- fd_set readfds;
- char buf[1]; // used to have larger buffer, but since non blocking fails...
+ ssize_t num1(1), num2(1);
+ char buf[4096];
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
+ /** @bug @b Solved: It sometimes did not get the whole input
+ since I changed to non blocking pipes. Now I have found
+ the solution to the problems: Non blocking IO does not
+ work in conjunction with @c select! Also the pipe must
+ not be nonblocking on both ends, but only on one. */
+ while (num1||num2||!res) try { // not end of files or child terminated
if (!res && (res=waitpid(pid, &s, WNOHANG)))
if (res!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0)
throw ExecutionFailedExc("execution failed", *_cmd);
- // select...
- FD_ZERO(&readfds);
- if (num1) FD_SET(stdOut.istream(), &readfds);
- if (num2) FD_SET(stdErr.istream(), &readfds);
- int n(mrw::max((num1?stdOut.istream():0),
- (num2?stdErr.istream():0)));
- timeval tm = {0, 10000};
- 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
+ if (num1<=0&&num2<=0) usleep(10000); // nothing to read last time
// check and handle stdout
- if (num>0 && FD_ISSET(stdOut.istream(), &readfds))
- if ((num1=read(stdOut.istream(), buf, sizeof(buf)))>0)
- _res += std::string(buf, num1);
- else if (num1==-1 && (errno!=EINTR&&errno!=EAGAIN))
- throw ExecutionFailedExc("readin stdout", *_cmd);
+ if (num1 && (num1=read(stdOut.istream(), buf, sizeof(buf)))>0)
+ _res += std::string(buf, num1);
+ else if (num1==-1 && (errno!=EINTR&&errno!=EAGAIN))
+ throw ExecutionFailedExc("readin stdout", *_cmd);
// check and handle stderr
- if (num>0 && FD_ISSET(stdErr.istream(), &readfds))
- if ((num2=read(stdErr.istream(), buf, sizeof(buf)))>0)
- _err += std::string(buf, num2);
- else if (num2==-1 && (errno!=EINTR&&errno!=EAGAIN))
- throw ExecutionFailedExc("readin stderr", *_cmd);
+ if (num2 && (num2=read(stdErr.istream(), buf, sizeof(buf)))>0)
+ _err += std::string(buf, num2);
+ else if (num2==-1 && (errno!=EINTR&&errno!=EAGAIN))
+ throw ExecutionFailedExc("readin stderr", *_cmd);
} catch (...) {
if (exc) throw;
_success = false;
return *this;
}
- std::cout<<"num1="<0
- && FD_ISSET(stdIn.ostream(), &writefds))
- if ((num0=write(stdIn.ostream(), in.c_str(), in.size()))>0) {
- if ((unsigned int)num00) {
+ if ((unsigned int)num00 && FD_ISSET(stdOut.istream(), &readfds))
- if ((num1=read(stdOut.istream(), buf, sizeof(buf)))>0)
- _res += std::string(buf, num1);
- else if (num1==-1 && (errno!=EINTR&&errno!=EAGAIN))
- throw ExecutionFailedExc("readin stdout", *_cmd);
+ if (num1 && (num1=read(stdOut.istream(), buf, sizeof(buf)))>0)
+ _res += std::string(buf, num1);
+ else if (num1==-1 && (errno!=EINTR&&errno!=EAGAIN))
+ throw ExecutionFailedExc("readin stdout", *_cmd);
// check and handle stderr
- if (num>0 && FD_ISSET(stdErr.istream(), &readfds))
- if ((num2=read(stdErr.istream(), buf, sizeof(buf)))>0)
- _err += std::string(buf, num2);
- else if (num2==-1 && (errno!=EINTR&&errno!=EAGAIN))
- throw ExecutionFailedExc("readin stderr", *_cmd);
+ if (num2 && (num2=read(stdErr.istream(), buf, sizeof(buf)))>0)
+ _err += std::string(buf, num2);
+ else if (num2==-1 && (errno!=EINTR&&errno!=EAGAIN))
+ throw ExecutionFailedExc("readin stderr", *_cmd);
} catch (...) {
if (exc) throw;
_success = false;
return *this;
}
- std::cout<<"num0="<