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>
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
||||||
|
|
||||||
$Log$
|
$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
|
Revision 1.6 2004/12/17 16:28:51 marc
|
||||||
stable implementation with select for both executes
|
stable implementation with select for both executes
|
||||||
|
|
||||||
@@ -38,6 +41,7 @@
|
|||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
#include <assert.h> // assert
|
#include <assert.h> // assert
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
mrw::ExecutionFailedExc::ExecutionFailedExc(const std::string& w,
|
mrw::ExecutionFailedExc::ExecutionFailedExc(const std::string& w,
|
||||||
const std::string& c)
|
const std::string& c)
|
||||||
throw(std::bad_exception):
|
throw(std::bad_exception):
|
||||||
@@ -129,7 +133,7 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
|
|||||||
program. */
|
program. */
|
||||||
_success = false;
|
_success = false;
|
||||||
_res = _err = "";
|
_res = _err = "";
|
||||||
mrw::Pipe stdOut, stdErr;
|
mrw::Pipe stdOut(true), stdErr(true);
|
||||||
if (!stdOut || !stdErr)
|
if (!stdOut || !stdErr)
|
||||||
throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd);
|
throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd);
|
||||||
pid_t pid(fork());
|
pid_t pid(fork());
|
||||||
@@ -142,8 +146,12 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
|
|||||||
throw ExecutionFailedExc("cannot close pipe", *_cmd);
|
throw ExecutionFailedExc("cannot close pipe", *_cmd);
|
||||||
ssize_t num1(-1), num2(-1);
|
ssize_t num1(-1), num2(-1);
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
char buf[4096];
|
char buf[1]; // used to have larger buffer, but since non blocking fails...
|
||||||
int res(0), s(0);
|
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
|
while (num1||num2) try { // not all end of file
|
||||||
if (!res && (res=waitpid(pid, &s, WNOHANG)))
|
if (!res && (res=waitpid(pid, &s, WNOHANG)))
|
||||||
if (res!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0)
|
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),
|
int n(mrw::max((num1?stdOut.istream():0),
|
||||||
(num2?stdErr.istream():0)));
|
(num2?stdErr.istream():0)));
|
||||||
timeval tm = {0, 10000};
|
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) throw ExecutionFailedExc("select failed", *_cmd);
|
||||||
if (num==0 && res==pid) break; // process ended, no data left
|
if (num==0 && res==pid) break; // process ended, no data left
|
||||||
// check and handle stdout
|
// check and handle stdout
|
||||||
@@ -175,6 +183,7 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
|
|||||||
_success = false;
|
_success = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
std::cout<<"num1="<<num1<<", num2="<<num2<<std::endl;
|
||||||
} else { // child
|
} else { // child
|
||||||
stdOut.close_in();
|
stdOut.close_in();
|
||||||
stdErr.close_in();
|
stdErr.close_in();
|
||||||
@@ -201,7 +210,7 @@ mrw::Exec& mrw::Exec::execute(const std::string& input, bool exc)
|
|||||||
_success = false;
|
_success = false;
|
||||||
_res = _err = "";
|
_res = _err = "";
|
||||||
mrw::Pipe stdIn(true), // child terminates if stdin is non-blocking
|
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)
|
if (!stdIn || !stdOut || !stdErr)
|
||||||
throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd);
|
throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd);
|
||||||
pid_t pid(fork());
|
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);
|
ssize_t num0(-1), num1(-1), num2(-1);
|
||||||
std::string in(input);
|
std::string in(input);
|
||||||
fd_set writefds, readfds;
|
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);
|
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
|
while (num0||num1||num2) try { // not all end of file
|
||||||
if (!res && (res=waitpid(pid, &s, WNOHANG)))
|
if (!res && (res=waitpid(pid, &s, WNOHANG)))
|
||||||
if (res!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0)
|
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),
|
mrw::max((num1?stdOut.istream():0),
|
||||||
(num2?stdErr.istream():0))));
|
(num2?stdErr.istream():0))));
|
||||||
timeval tm = {0, 10000};
|
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) throw ExecutionFailedExc("select failed", *_cmd);
|
||||||
if (num==0 && res==pid) break; // process ended, no data left
|
if (num==0 && res==pid) break; // process ended, no data left
|
||||||
// check and handle stdin
|
// check and handle stdin
|
||||||
@@ -261,6 +274,7 @@ mrw::Exec& mrw::Exec::execute(const std::string& input, bool exc)
|
|||||||
_success = false;
|
_success = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
std::cout<<"num0="<<num0<<", num1="<<num1<<", num2="<<num2<<std::endl;
|
||||||
} else { // child
|
} else { // child
|
||||||
stdIn.close_out();
|
stdIn.close_out();
|
||||||
stdOut.close_in();
|
stdOut.close_in();
|
||||||
|
Reference in New Issue
Block a user