arun11299 / cpp-subprocess

Subprocessing with modern C++
Other
456 stars 90 forks source link

I can send() but I have no way of closing the input channel #21

Closed mohamedAlaaK closed 5 years ago

mohamedAlaaK commented 5 years ago
#include <subprocess.hpp>

using namespace std;
using namespace subprocess;

int main()
{
    vector<Popen> sub_processes;
    for ( int i = 0 ; i < 5 ; i++ )
    {
        sub_processes.emplace_back(Popen({"cat"},input{PIPE}));
        sub_processes[i].send("3 5\n", 5);
    }

    for ( int i = 0 ; i < 5 ; i++ )
    {
        sub_processes[i].wait(); // waits forever
    }
}

In the code above I spawn 5 instances of cat. I call send() to each of them. In the second loop we call wait but it waits forever. I suspect that cat is still waiting for more input because the channel was not closed.

communicate() does close the channels. But I need to use send() is there a function I am missing that can close the channels?

Thanks in advance.

mohamedAlaaK commented 5 years ago
#include <subprocess.hpp>

using namespace std;

using namespace subprocess;

int main()
{
    auto p = Popen({"cat", "-"}, input{PIPE}, output{"cat_fredirect.txt"});
    auto msg = "through stdin to stdout";
    p.send(msg, strlen(msg));
    p.wait();
}

i tried the code in the readme.md and it still waits forever. Haalp!

mohamedAlaaK commented 5 years ago

I made detail::Streams stream_ public and reset() it after send() and it worked!

    for ( int i = 0 ; i < 5 ; i++ )
    {
        sub_processes.emplace_back(Popen({"cat", "-"},input{PIPE}));
        sub_processes[i].send("3 5\n", 5);
        sub_processes[i].stream_.input_.reset();
    }
arun11299 commented 5 years ago

Hi @mohamedAlaaK

You didn't have to make "stream_" public for this. You could have instead done:

fclose(sub_processes[i].input());

mohamedAlaaK commented 5 years ago

Hi @arun11299 first of all nice profile picture :D secondly, i used that line instead of resetting the shared ptr and it did crash the program. after going out of scope the default constructor was called and it tried to delete the shared ptr which was already deleted as a raw ptr using fclose(). is there something i am missing here?

arun11299 commented 5 years ago

Ah..ofcourse. I will provide an API to fix it. Thanks :)

mohamedAlaaK commented 5 years ago

i am looking forward to that. have a nice day

arun11299 commented 5 years ago

I have added this test.

  void test_cat_send_terminate()
  {
    std::cout << "Test::test_cat_send_terminate" << std::endl;
    std::vector<sp::Popen> pops;

    for (int i=0; i < 5; i++) {
      pops.emplace_back(sp::Popen({"cat", "-"}, sp::input{sp::PIPE}));
      pops[i].send("3 5\n", 5);
      pops[i].close_input();
    }

    for (int i=0; i < 5; i++) {
      pops[i].wait();
    }

    std::cout << "END_TEST" << std::endl;
  }

Let me know if it works for you.

And, Happy new year!!

mohamedAlaaK commented 5 years ago

yeah it works greatly thanks for this beautiful project. Happy new year.