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