Issue in periodically reading contents of stdout redirected to pipe using dup2
I have to periodically read contents of stdout which is redirected to file. please help me to resolve issue.
My problem in detail is that i have two thread in first thread , i have to execute a c file which is continously writing output to stdout(i.e writing hello world in infinite loop) and in second thread i have to retrieve line by line output periodically from stdout and store in buffer.
Below is the code for above requirement: please suggest me is my approach right? and how to implement entryOpThread() method so that it will read contents of stdout periodically whether should i use read() system call or getLine()or any other method to read line by line from pipe(stdout is redirected to this pipe). In this example exec thread is executing test.c which is continuouslly printing hello world on stdout, so according to my requirement i have to read this output line by line("Hello world") continuouslly in Outputthread from pipe and store it in buffer //
#include<iostream>
#include<pthread>
#include<unistd.h>
#include<sys/wait.h>
const int MAX_LENGTH=100;
using namespace std;
//! file descriptor to duplicate the system standard input
int inputPIPE[2];
//! file descriptor to duplicate the system standard output
int OutputPipe[2];
//!Thread to retrieve output
//!
pthread_t OpThread;
//!Thread to execute script
//!
pthread_t ExecThread;
//! entry point of the exec thread
void *entryExecThread(void * obj)
{
//create a child process to launch the script
int lPid;
lPid=fork();
//connect read end of the pipe to the standard input
if(dup2(inputPIPE[0],STDIN_FILENO)==-1)
{
//throw exception
}
//connect write end of the pipe to the standard output
if(dup2(OutputPipe[1],STDOUT_FILENO)==-1)
{
//throw exception
}
if(lPid==0)
{
execvp("./test",NULL);
}
else
{
int mProcessId=lPid;
waitpid(mProcessId,NULL,0);
}
return NULL;
}
//! entry point of the output thread
void *entryOpThread(void * obj)
{
//read contents of stdout periodically
char *lMssg=new char[MAX_LENGTH];
read(OutputPipe[0],lMssg,MAX_LENGTH);
FILE *fd=fdopen(OutputPipe[0],"r");
int lBufferLength=MAX_LENGTH;
/* while(true)
{
getline(&lMssg,(size_t * )&lBufferLength,fd);
// push message to the output buffer
if (lMssg !=NULL)
{
pthread_mutex_lock( &mOutputBufferMutex);
mOutputBuffer.push(lMssg);
pthread_mutex_unlock( &mOutputBufferMutex);
}
}
*/
}
int main() {
//call to pipe system call
if(pipe(inputPIPE)==-1)
{
printf("ERROR IN OPENIN开发者_JS百科G FILE \n");
}
if(pipe(OutputPipe)==-1)
{
printf("ERROR IN OPENING FILE\n ");
}
//CREATE OUTPUT THREAD TO RETRIEVE OUTPUT
if (pthread_create(&OpThread,0,entryOpThread,NULL)!=0)
{
//throw exception
printf("Creation of Output thread failed for Script with ID\n");
}
//Create execution thread to launch script
pthread_t execThread;
if (pthread_create(&ExecThread,0,entryExecThread,NULL)!=0)
{
//Stop output thread
pthread_cancel(OpThread);
//throw exception
printf("Creation of Execution thread failed for Script with ID\n");
}
}
test.c
#include <stdio.h>
#include "string.h"
//using namespace std;
int main() {
int i=0;
while(i<500)
{
printf("!!!Hello World!!! \n" ); // prints !!!Hello World!!!
//extracting header and data from message
sleep(5);
i++;
}
return 0;
}
Data sent to a pipe is buffered so you don't need another buffer. Just read the data from a pipe whenever there is a need to. You can test whether there is a data to read using poll
function. You don't need the reader thread.
Also you don't need exec thread because you are fork
'ing anyway.
Besides your application would terminate almost immediately because the main thread would end up after firing secondary threads.
Other thing to point out is that you should close unneeded handles. pipe
opens 2 handles, fork
duplicates all opened handles, dup2
duplicate a handle. You didn't close any.
If you just want to read output of some process, run it using popen
. Below short example.
main app:
int main()
{
FILE *f = popen("./test", "r"); // open the process
/* Your application is busy now, but the process runs and outputs */
sleep(5);
/* Now assume you need some data - just read it */
int c;
while (0 <= (c = fgetc(f))) putchar(c);
}
test app:
int main()
{
int i;
for (i = 0; i < 10; i++) {
puts("Hello world!");
fflush(stdout);
sleep(1);
}
}
If this solution doesn't fit your needs then write what's the problem.
精彩评论