chibagoです。
先日、fork&pipeのプログラムが異常終了するという件でご相談させていただきましたが、
原因が特定できましたのでアドバイスをいただければと思います。
PipeToStandardIO::PipeToStandardIO(const std::string command){
int pid;
if((pid = this->generate_pipe(command)) == 0){
std::cout<<"Cannot generate pipe"<<std::endl;
exit(-1);
}
this->open_stream();
}
PipeToStandardIO::~PipeToStandardIO(){
if (this->read_stream_status != "closed")
this->close_standard_output();
if (this->write_stream_status != "closed")
this->close_standard_input();
}
void PipeToStandardIO::set_standard_input(const std::string& str){
fputs(str.c_str(), this->write_stream);
}
std::string PipeToStandardIO::get_standard_output(){
std::ostringstream os;
char buf[1000];
while(fgets(buf, 1000, this->read_stream) !=NULL){
os << buf;
}
return os.str();
}
void PipeToStandardIO::close_standard_output(){
if (this->read_stream_status != "closed")
fclose(this->read_stream);
this->read_stream_status = "closed";
}
void PipeToStandardIO::close_standard_input(){
if (this->write_stream_status != "closed")
fclose(this->write_stream);
this->write_stream_status = "closed";
}
int PipeToStandardIO::generate_pipe(const std::string command){
int pipe_c2p[2], pipe_p2c[2];
int pid;
/* Create two pipes. */
if(pipe(pipe_c2p)<0){
std::cout<<"Cannot create a pipe of child to parent."<<std::endl;
return -1;
}
if(pipe(pipe_p2c)<0){
std::cout<<"Cannot create a pipe of parent to child."<<std::endl;
close(pipe_c2p[0]);
close(pipe_c2p[1]);
return -1;
}
/* Invoke processs */
if((pid = fork()) < 0 ){
std::cout<<"Cannot invoke processs."<<strerror(errno)<<std::endl;
close(pipe_c2p[0]);
close(pipe_c2p[1]);
close(pipe_p2c[0]);
close(pipe_p2c[1]);
return -1;
}
/* Implimentation of child. */
if(pid == 0){
close(pipe_p2c[1]);
close(pipe_c2p[0]);
dup2(pipe_p2c[0], 0);
dup2(pipe_c2p[1], 1);
close(pipe_p2c[0]);
close(pipe_c2p[1]);
if (execlp("sh", "sh", "-c", command.c_str(), NULL) < 0){
std::cout<<"Cannot invoke child processs."<<strerror(errno)<<std::endl;
close(pipe_p2c[0]);
close(pipe_c2p[1]);
exit(1);
}
}
close(pipe_p2c[0]);
close(pipe_c2p[1]);
this->fd_w = pipe_p2c[1];
this->fd_r = pipe_c2p[0];
return pid;
}
void PipeToStandardIO::open_stream(){
this->read_stream = fdopen(this->fd_r, "r");
if (this->read_stream == NULL){
std::cout<<"Cannot establish a read stream."<<strerror(errno)<<std::endl;
exit(-1);
}
this->write_stream = fdopen(this->fd_w, "w");
if (this->write_stream == NULL){
std::cout<<"Cannot establish a write stream."<<strerror(errno)<<std::endl;
exit(-1);
}
}
パイプがつながりましたらexeclp関数でプログラムを実行します。
このプログラムを使って何回も他のプログラムを呼び出して
計算をしておりますが、execlpにより呼び出されたプログラム
が終了してもプロセスとして残り続けているようです。(psで確認しました。)
そもそも、execlpは実行後にリソースを解放してくれるようなことがネットで
書かれておりますが、残ってしまうのはpipeやforkを用いているからでしょうか。
この問題を回避する方法もしくはプロセスを明示的に終了させる
方法をご存知でしたらご指導いただければ幸いです。