Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::process write to stdin

I have a thread starting a boost::process application, with the code the thread runs like this:

void Service::Run()
{
    printf("Starting thread for service ID %i\n", this->sid);

    // Set up a stream sink for stdout, stderr and stdin
    bprocess::pipe pstdIn    = create_pipe();
    bprocess::pipe pstdOut   = create_pipe();
    file_descriptor_sink      fdSink(pstdIn.sink, close_handle);
    file_descriptor_source    fdSrc(pstdOut.sink, close_handle);

    // Set up the read write streams
    this->stdIn  = new fdistream(fdSink);
    this->stdOut = new fdostream(fdSrc);

    // Execute the service
    try
    {
        child proc = execute(
            set_args(this->args),
            inherit_env(),
            bind_stdin(fdSrc),

            throw_on_error()
        );

        printf("PID: %i\n", proc.pid);

        // Wait for the application to end then call a cleanup function
        int exit_code = wait_for_exit(proc);

        printf("Service died, error code: %i\n", exit_code);
    }
    catch(boost::system::system_error err)
    {
        printf("Something went wrong: %s\n", err.what());
    }

    this->manager->ServiceDie(this->sid);

    return;
}

As this function is a blocking one, it essentially waits for the service to be killed (Externally or as I need; input via stdin to gracefully stop the application).

I have no idea how to write to the stdin of the child process. I have tried this:

*(this->stdIn) << "stop\n";

inside a public function in the class of Service that's being called in another thread (Manager class). However this yeilds no results.

How can I write to the stdin of the child proc?

like image 750
Zinglish Avatar asked Oct 20 '22 14:10

Zinglish


1 Answers

Here's a demo adapted from sample here:

You can see it Live on Coliru Sadly that's pushing the limits of Coliru. May be later:

#include <boost/process.hpp> 
#include <boost/assign/list_of.hpp> 
#include <string> 
#include <vector> 
#include <iostream> 

using namespace boost::process; 

int main() 
{ 
    std::string exec = find_executable_in_path("rev"); 
    std::vector<std::string> args = boost::assign::list_of("rev"); 

    context ctx; 
    ctx.environment = self::get_environment(); 
    ctx.stdin_behavior = capture_stream(); 
    ctx.stdout_behavior = capture_stream(); 
    child c = launch(exec, args, ctx); 

    postream &os = c.get_stdin();
    pistream &is = c.get_stdout(); 

    os << "some\ncookies\nfor\ntasting";
    os.close();

    std::cout << is.rdbuf(); 
} 

Output:

emos
seikooc
rof
gnitsat

Now, if you need it truly asynchronous, there's another sample using Boost Asio further down that page

like image 193
sehe Avatar answered Oct 30 '22 00:10

sehe