2

I am writing C++ code that accepts a command line argument, passes it to a system command like echo and prints the response. To communicate with external process, I am using tiny-process-library. The problem with my current code is that it has to wait for a configured delay of 5 seconds.

When I tried moving my code into the Process object, I get below compilation error.

Test.cpp: In lambda function:
Test.cpp:29:3: error: ‘p_Request’ is not captured

Could somebody please help me to remove the delay and populate the Result object once the external command completes its execution?

Test.cpp

#include "process.hpp"
#include <iostream>
#include <string>

using namespace TinyProcessLib;
using namespace std;

class Request{

    public:

        string s_Request;

        bool b_requestProcessed = false;

        bool b_error = false;

        string s_Response = "No response yet";

};

void processCommand( Request* );

int main(int argc, char *argv[]){

    Request *p_Request = new Request();
    p_Request->s_Request = argv[1];
    processCommand( p_Request );
    while(!p_Request->b_requestProcessed){
    }
    cout << p_Request->s_Response << endl;
}


void processCommand( Request* p_Request ){

    if(!p_Request){
        p_Request->b_error = true;
        return;
    }
    auto output=make_shared<string>();
    Process process(string("echo ") + string(p_Request->s_Request), "", [output](const char *bytes, size_t n){
         *output+=string(bytes, n);
    });
    // Help me to remove this delay
    this_thread::sleep_for(chrono::seconds(5));
    p_Request->s_Response=*output;
    auto exit_status=process.get_exit_status();
    if(exit_status == 0){
        p_Request->b_requestProcessed = true;
        p_Request->b_error = false;
    }else{

        p_Request->b_error = true;
        p_Request->s_Response="Command Execution Failed";
    }

}

Compilation Command

g++ -std=c++11 -pthread process.cpp process_unix.cpp Test.cpp -o Test

Result with Delay

./Test  "Hello Stack Overflow"
Hello Stack Overflow

Result without Delay

./Test  "Hello Stack Overflow"
[[EMPTY_LINE]]
vgru
  • 49,838
  • 16
  • 120
  • 201
JSN
  • 2,035
  • 13
  • 27
  • I would suggest taking a careful look at the "Process.h" file that you've not posted; there should be something in there that will allow you wait for the process to complete. – UKMonkey Aug 03 '17 at 14:09
  • _error: ‘p_Request’ is not captured_ - have you tried to capture it? –  Aug 03 '17 at 14:11
  • @UKMonkey - Here's the source of process.hpp https://github.com/eidheim/tiny-process-library/blob/master/process.hpp – JSN Aug 03 '17 at 14:12
  • @manni66 - Could you please point me to the syntax for capturing? I am totally new to this. – JSN Aug 03 '17 at 14:12
  • 1
    "///Wait until process is finished, and return exit status. int get_exit_status() noexcept;" So just call this before you attempt to touch the output – UKMonkey Aug 03 '17 at 14:13
  • Your async lambda could signal a mutex after it writes the string, and the main thread could simply wait on the mutex. But a better question is whether the lambda is only called once, or the data can be incoming in packets? So an approach which would make more sense would be to enqueue incoming data into a RX fifo, and then either signal external code that it should parse, or immediately parse the whole buffer inside the callback. – vgru Aug 03 '17 at 14:14

1 Answers1

4
this_thread::sleep_for(chrono::seconds(5));
p_Request->s_Response=*output;
auto exit_status=process.get_exit_status();

Edit to

auto exit_status=process.get_exit_status();
p_Request->s_Response=*output;

The .get_exit_status() waits for the process to complete, and your =*output makes a copy. So in the first version you're copying an empty string (as the process hasn't finished) and the second, it's awaiting the process to complete before making the copy.

UKMonkey
  • 6,941
  • 3
  • 21
  • 30