Redirecting output from child processes - c++

In my c++ windows app I start multiple child processes and I want them to inherit parent's stdout/stderr, so that if output of my app is redirected to some file then that file would also contain output of all child processes that my app creates.
Currently I do that using CreateProcess without output redirection. MSDN has a sample how to redirect output: Creating a Child Process with Redirected Input and Output, but I want to see what alternative do I have. Simplest is to use system and call it from a blocking thread that waits for child to exit. All output is then piped back to parent's stdout/stderr, however in parent process I do not have a chance to process stdout data that comes from child.
There are also other functions to start processes on windows: spawn, exec, which might be easier to port to posix systems.
What should I use if I want it to work on linux/osx? What options do I have if I want it to work on UWP aka WinRT? I might be totally ok with system called from a blocking thread, but perhaps I'd prefer to be able to have more control on process PID (to be able to terminate it) and process stdout/stderr, to prepend each line with child##: for example.

The boost libraries recently released version 1.64 which includes a new boost::process library.
In it, you're given a C++ way to be able to redirect output to a pipe or asio::streambuf, from which you can create a std::string or std::istream to read whatever your child process wrote.
You can read up on boost::process tutorials here, which shows some simple examples of reading child output. It does make heavy use of boost::asio, so I highly recommend you read up on that too.

Related

how to interact with a command line program from c++ code

For my computer science class final project, I need to interact with a SQL database. Only problem is, my prof won't install the SQL c++ API for me. Is there a way I can still interact with SQL without the API?
If I'm understanding your question correctly, you want your program to be able to launch a child process (an SQL command line program in this case), and then be able to read the text it receives from the child process's stdout and/or stderr, and write text to the child process's stdin, the same way a user would if he/she were running that program interactively.
The answer is yes, it is possible to do this, although it takes some work. Under Linux/Unix/MacOSX, you can call forkpty() to spawn a child process -- the parent process will get a socket (via forkpty's first argument) that you can use to communicate with the child process's stdin and stdout. In the child process, you can then call execvp (or one of its variants) to run the SQL program in that process;
Under Windows, it's a bit more complex -- you'll need to set up some pipes and then call CreateProcess() to launch the child process, and communicate with it through those pipes. Microsoft has a page on the topic (including example code) here.

c++ How to start a process with new stdin and stdout

I am writing a program in openFrameworks a c++ framework. I want to start another app and communicate with it over stdin and stdout. I can start a new thread conveniently using the ofThread class. I had planned on creating two pipes and redirecting the std in and out of the thread to the pipes (using dup2), but unfortunately, this redirects the pipes for the whole app, not just the thread.
Is there a way I can start another app and be able to reads its output and provide it input?
Instead of another thread you'll need to create a child process using the fork() function (which might involve another thread intrinsically).
The difference is, that fork creates a complete copy of the parent process environment that should be shown on an exec() call within scope of the child process, while just exec() from a thread tries to share all the resource from it's parent process (thread) and thus might lead to unexpected concurrency (race conditon) problems.
If your "another app" is implemented as a subthread within your existing program, you don't need to redirect stdin and stdout to communicate with it over pipes. Just pass the pipe file descriptors to the subthread when you start it up. (You can use fdopen to wrap file descriptors in FILE objects. If you have dup2 and pipe, you have fdopen as well.)

Writing stderr from one process to another process c++/unix

I have one application where parent process launches jobs over distributed farm system like lsf/vnc .
Now what I want is whenever there is any error reported in thier respective log by any of the jobs launch , error should be redirected to main stdout screen of parent process. so that there is no need to monitor log of each job separately.
I have never used pipe/semaphores in my codes but I can learn that if needed.
Please suggest some efficient solution. I am working on Linux/Solaris platform.
Thanks
Depending on how you launch the subprocesses there are different mechanics how to set their standard handles.
In general, you'll have to set their stderr handle to be the same your stdout handle.
Keep in mind that this has nothing to do with the "logs" that you mention; it's about what your subject says (redirecting stderr).
If you want the stderr of the children to be the same as the stdout of the parent, then you may be able to simply launch the parent with its stderr tied to its stdout. If cmd is the command to launch the parent, try:
$ cmd 2>&1
You probably should use dup2() library call in order to duplicate STDERR in the child process to desired file descriptor, for example to STDOUT of any other descriptor, which can be opened before by the parent process and inherited by the child process after fork().
Try to read manula page for "dup2" call.

Showing a progress bar while SFX archive is extracting

I'm writing a program with C++ and by native Win32 API. I'm creating a process from a SFX archive EXE in silent mode that no GUI is shown to user. But I want to show a progress bar in my application, while the SFX archive extracting.
How can I do that?
Thanks.
If the process you create produces some textual output to the standard output then you can probably parse that output somehow and show the progress. To know if it does, activate it in a command line windows and watch what you get from it.
win32's CreateProcess() allows you to redirect the standard output of the process to a pipe. This way you can receive the output as soon as it is produced.
If the process you're creating doesn't report its progress somehow then there's really not much you can do. You can try to come up with function between the size of the file and the average time it takes to extract it and then fake a progress bar. That will serve the purpose of setting the user's mind at ease but nothing more.
--Edit
The call to CreateProcess() returns as soon as the process is created. CreateProcess() fills up the struct PROCESS_INFORMATION with the handles of the process it creates. it contains the handle of the main thread of the process. If you want to wait for the process to finish you can WaitForSingleEvent() on that thread handle which gets signaled when the thread terminates. Don't forget to CloseHandle() those handles when you're done with them.

Windows C++: How can I redirect stderr for calls to fprintf?

I am wrapping existing C++ code from a BSD project in our own custom wrapper and I want to integrate it to our code with as few changes as possible. This code uses fprintf to print to stderr in order to log / report errors.
I want to redirect this to an alternative place within the same process. On Unix I have done this with a socketpair and a thread: one end of the socket is where I send stderr (via a call to dup2) and the other end is monitored in a thread, where I can then process the output.
This does not work on Windows though because a socket is not the same as a file handle.
All documents I have found on the web show how to redirect output from a child process, which is not what I want. How can I redirect stderr within the same process getting a callback of some sort when output is written? (and before you say so, I've tried SetStdHandle but cannot find any way to make this work)...
You can use a similar technique on Windows, you just need to use different words for the same concepts. :) This article: http://msdn.microsoft.com/en-us/library/ms682499.aspx uses a win32 pipe to handle I/O from another process, you just have to do the same thing with threads within the same process. Of course, in your case all output to stderr from anywhere in the process will be redirected to your consumer.
Actually, other pieces of the puzzle you may need are _fdopen and _open_osfhandle. In fact, here's a related example from some code I released years ago:
DWORD CALLBACK DoDebugThread(void *)
{
AllocConsole();
SetConsoleTitle("Copilot Debugger");
// The following is a really disgusting hack to make stdin and stdout attach
// to the newly created console using the MSVC++ libraries. I hope other
// operating systems don't need this kind of kludge.. :)
stdout->_file = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
stdin->_file = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT);
debug();
stdout->_file = -1;
stdin->_file = -1;
FreeConsole();
CPU_run();
return 0;
}
In this case, the main process was a GUI process which doesn't start with stdio handles at all. It opens a console, then shoves the right handles into stdout and stdin so the debug() function (which was designed as a stdio interactive function) can interact with the newly created console. You should be able to open some pipes and do the same sort of thing to redirect stderr.
You have to remember that what MSVCRT calls "OS handles" are not Win32 handles, but another layer of handles added just to confuse you. MSVCRT tries to emulate the Unix handle numbers where stdin = 0, stdout = 1, stderr = 2 and so on. Win32 handles are numbered differently and their values always happen to be a multiple of 4. Opening the pipe and getting all the handles configured properly will require getting your hands messy. Using the MSVCRT source code and a debugger is probably a requirement.
You mention that you don't want to use a named pipe for internal use; it's probably worth poining out that the documentation for CreatePipe() states, "Anonymous pipes are implemented using a named pipe with a unique name. Therefore, you can often pass a handle to an anonymous pipe to a function that requires a handle to a named pipe." So, I suggest that you just write a function that creates a similar pipe with the correct settings for async reading. I tend to use a GUID as a string (generated using CoCreateGUID() and StringFromIID()) to give me a unique name and then create the server and client ends of the named pipe with the correct settings for overlapped I/O (more details on this, and code, here: http://www.lenholgate.com/blog/2008/02/process-management-using-jobs-on-windows.html).
Once I have that I wire up some code that I have to read a file using overlapped I/O with an I/O Completion Port and, well, then I just get async notifications of the data as it arrives... However, I've got a fair amount of well tested library code in there that makes it all happen...
It's probably possible to set up the named pipe and then just do an overlapped read with an event in your OVERLAPPED structure and check the event to see if data was available... I don't have any code available that does that though.