I write a inter process program which start sub processes in main program. These processes communicate as they are running independently in shell. I use pipe(), dup2() to connect stdin, stdout of sub process.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <string>
#include <sstream>
#define READ 0
#define WRITE 1
int popen3(const char* command, int & pid, FILE*& fdr, FILE*& fdw)
{
pid_t child_pid;
int pip1[2]={-1,-1}; // [parent-read, clild-write]
int pip2[2]={-1,-1}; // [clild-read, parent-write]
pipe2(pip1, 0);
pipe2(pip2, 0);
if((child_pid = fork()) == -1)
{
perror("fork");
//exit(1);
return errno;
}
/* child process */
if (child_pid == 0)
{
close(pip1[READ]);
close(pip2[WRITE]);
dup2(pip1[WRITE], STDOUT_FILENO); // child-write
dup2(pip2[READ], STDIN_FILENO); // child-read
close(pip1[WRITE]);
close(pip2[READ]);
setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh
execl("/bin/sh", "/bin/sh", "-c", command, NULL);
exit(0);
}
else // parent process
{
close(pip1[WRITE]);
close(pip2[READ]);
}
pid = child_pid;
fdr = fdopen(pip1[READ], "r"); // parent-read
fdw = fdopen(pip2[WRITE], "w"); // parent-write
return 0;
}
int main()
{
int pid;
string command = "python3";
FILE *fpw = nullptr, *fpr = nullptr;
if (popen3(command.c_str(), pid, fpr, fpw) !=0) {
printf("popen3 error\n");
exit(1);
}
char command_out[10] = {0};
if (fpr!=nullptr)
fcntl(fileno(fpr), F_SETPIPE_SZ, 0);
if (fpw!=nullptr)
fcntl(fileno(fpw), F_SETPIPE_SZ, 0);
if (fpw!=nullptr){
//fcntl(fileno(fpw), F_SETPIPE_SZ, 100);
const char* py="import os; os.write(2, b'py out stderr\\n'); print('hello'+' world')\n";
fwrite(py, 1, strlen(py), fpw);
}
else {
printf("fpw null\n");
}
if (fpr!=nullptr){
sleep(1);
fcntl(fileno(fpr), F_SETFL, O_NONBLOCK);
while (fread(command_out, 1, 10, fpr) > 0)
printf("#### %s", command_out);
}
else {
printf("fpr null\n");
}
if (fpw!=nullptr){
const char* py="import os; os.write(2, b'py out stderr\\n'); print('hello'+' world'); exit()\n";
fwrite(py, 1, strlen(py), fpw);
}
else {
printf("fpw null\n");
}
pclose3(fpr, fpw, pid);
return 0;
}
OUTPUT:
py out stderr
py out stderr
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
BrokenPipeError: [Errno 32] Broken pipe
It seems that it closed child to parent pipe. I'm fused to fix this. This may be the right output:
Python 3.8.10 (default, .... (from sub process stderr and directed to shell)
py out stderr
hello world (from sub process stdout and fread and printf to shell)
py out stderr
hello world
I have read the following questions but still not fix my problem.
Bi-directional inter-process communication using two pipes
And, here is a very clear tutorial: http://unixwiz.net/techtips/remap-pipe-fds.html
Thanks!