Code Monkey home page Code Monkey logo

cpp-subprocess's Introduction

[Subprocessing in C++]

Design Goals

The only goal was to develop something that is as close as python2.7 subprocess module in dealing with processes. Could not find anything similar done for C++ and here we are.

This library had these design goals:

  • Intuitive Interface. Using modern C++ features, made the API usage as simple as that in python in most cases and even better in some (See pipiing example).

  • Correctness. Dealing with processes is not a simple job. It has many low level details that needs to be taken care of. This library takes care of dealing with those low level details making it easier to launch processes.

  • Error Handling. Currently the error handling is achieved via the use of exceptions. It is important that no errors are ignored silently. I am working towards achieving this goal, but most of the error conditions have been taken care of.

Supported Platforms

This library supports MAC OS and Linux.

Support for Windows is limited at this time. Please report any specific use-cases that fail, and they will be fixed as they are reported.

Integration

Subprocess library has just a single source subprocess.hpp present at the top directory of this repository. All you need to do is add

#inlcude "cpp-subprocess/subprocess.hpp"

using namespace subprocess;
// OR
// namespace sp = subprocess; 
// Or give any other alias you like.

to the files where you want to make use of subprocessing. Make sure to add necessary switches to add C++11 support (-std=c++11 in g++ and clang).

Checkout http://templated-thoughts.blogspot.in/2016/03/sub-processing-with-modern-c.html as well.

Compiler Support

Linux - g++ 4.8 and above Mac OS - Clang 3.4 and later Windows - MSVC 2015 and above

Examples

Here are few examples to show how to get started:

  1. Executing simple unix commands The easy way:
auto obuf = check_output({"ls", "-l"});
std::cout << "Data : " << obuf.buf.data() << std::endl;
std::cout << "Data len: " << obuf.length << std::endl;

More detailed way:

auto p = Popen({"ls", "-l"}, output{PIPE});
auto obuf = p.communicate().first;
std::cout << "Data : " << obuf.buf.data() << std::endl;
std::cout << "Data len: " << obuf.length << std::endl;
  1. Output redirection Redirecting a message input to cat command to a file.
auto p = Popen({"cat", "-"}, input{PIPE}, output{"cat_fredirect.txt"});
auto msg = "through stdin to stdout";
p.send(msg, strlen(msg));
p.wait();

OR

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

OR Reading redirected output from stdout

auto p = Popen({"grep", "f"}, output{PIPE}, input{PIPE});
auto msg = "one\ntwo\nthree\nfour\nfive\n";
p.send(msg, strlen(msg));
auto res = p.communicate();

std::cout << res.first.buf.data() << std::endl;
  1. Piping Support Your regular unix command piping

Ex: cat subprocess.hpp | grep template | cut -d, -f 1

auto cat = Popen({"cat", "../subprocess.hpp"}, output{PIPE});
auto grep = Popen({"grep", "template"}, input{cat.output()}, output{PIPE});
auto cut = Popen({"cut", "-d,", "-f", "1"}, input{grep.output()}, output{PIPE});
auto res = cut.communicate().first;
std::cout << res.buf.data() << std::endl;
  1. Easy Piping There is another way to do piping for simple commands like above:
auto res = pipeline("cat ../subprocess.hpp", "grep Args", "grep template");
std::cout << res.buf.data() << std::endl;

The commands provided to the pipeline function is in the order that would have appeared in your regular unix command.

  1. Environment variables

For example, if a shell script requires some new environment variables to be defined, you can provide it with the below easy to use syntax.

int st= Popen("./env_script.sh", environment{{
                                   {"NEW_ENV1", "VALUE-1"},
                                   {"NEW_ENV2", "VALUE-2"},
                                   {"NEW_ENV3", "VALUE-3"}
             }}).wait();
assert (st == 0);
  1. Other examples There are lots of other examples in the tests with lot more overloaded API's to support most of the functionalities supported by python2.7.

License

The class is licensed under the MIT License:

Copyright © 2016-2018 [Arun Muralidharan]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

cpp-subprocess's People

Contributors

adamkewley avatar arun11299 avatar bdangit avatar bibermann avatar cr4shov3rrid3 avatar damageboy avatar darkdimius avatar deanmsands3 avatar dilshodm avatar drakklord avatar elazarl avatar gerardwx avatar hebasto avatar humaniam avatar ilue avatar jez avatar jvilk-stripe avatar littlesoftware avatar maged avatar mohamedalaak avatar obiwahn avatar philippewarren avatar santaclose avatar sokolmish avatar sorakatadzuma avatar xoviat avatar yytdfc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cpp-subprocess's Issues

Some windows errors

First - thank you for this effort.
I'm studying on a program that using subprocess,but occurs some problems:
1、“initializer list” cannot convert to “subprocess::environment”
2、Microsoft C++ abnormal: subprocess::OSError
and i work on windows10, visual studio 2017, is there any solutions for these problems,thanks a lot.

Calling Popen with a result of util::split doesn't compile

It would not be a stretch to expect this:

    auto proc = Popen(subprocess::util::split(command), error{PIPE}, cwd{where});

to compile.
Unfortunately it gives the following error:

/home/pklos/projects/(...).cpp:70:80: error: no matching function for call to ‘subprocess::Popen::Popen(std::vector<std::__cxx11::basic_string<char> >, subprocess::error, subprocess::cwd)’
     auto proc = Popen(subprocess::util::split(command), error{PIPE}, cwd{where});

I don't see another equivalent of python shlex.split in your library.

Issue with quotes on windows

I'm trying to run this command explorer /select,"C:\Windows" using subprocess::call, it should open a file explorer window with the "Windows" folder selected. However, the library always ends up surrounding all arguments with double quotes, and my double quotes are prepended with an extra backslash, causing the file explorer to open the "Documents" folder (no idea why). So, how should I use the library to run this specific command? I tried passing both, a vector and a string to the call command. Maybe something needs to be tweaked so arguments are not always surrounded with double quotes?
image
image

Buffer class is badly designed and superfluous

The class Buffer has

  std::vector<char> buf;
  size_t length = 0;

This is a bad interface design because the length field duplicates the buf.size(). At what situations can those differ? Should they differ? It is not documented and unclear.

Furthermore, the class can (and arguably should) be replaced with std::string.

memory leak

In the following code:

      int read_bytes = util::read_atmost_n(
                                  fdopen(err_rd_pipe, "r"),
                                  err_buf,
                                  SP_MAX_ERR_BUF_SIZ);
      close(err_rd_pipe);

The value returned by fdopen() is not closed. This causes memory leak.
If you call fclose(), it will close err_rd_pipe. So close(err_rd_pipe) is not necessary.

How to communicate with interactive shell script?

Hi Arun, I'm trying to open a interactive shell script then send command and get response, again and again, but only firstly Popen script can get response by communicate function, after this, used opened Popen handle to 'send' msg, can't get response by communicate. Could you help share how to do this? Appreciate it!

Blocking when using read_all with socket stream

I am using function read_all() but process is blocking.
I find this happen here:
int read_bytes = read(fd, buf + rbytes, read_upto - rbytes);

Solution:

      fd_set fds;
      struct timeval timeout;

      timeout.tv_sec = 3; /* timeout in secs */
      timeout.tv_usec = 10000;
      FD_ZERO(&fds);
      FD_SET(fd, &fds);
      if (select(fd + 1, &fds, NULL, NULL, &timeout) > 0) {
        read_bytes = read(fd, buf + rbytes, read_upto - rbytes);
      } else {
        std::cout << "Time out" << std::endl;
      }

MinGW support

MinGW (Min. GNU for Windows) also requires the Windows-specific code, but doesn't #define _MSC_VER. All the Windows-specific fixes are ignored. Using a combined definition would solve this.

Windows support for environment variables

In the Windows sp::Popen, we have this:

  // Create the child process.
  bSuccess = CreateProcessW(NULL,
                            szCmdline,    // command line
                            NULL,         // process security attributes
                            NULL,         // primary thread security attributes
                            TRUE,         // handles are inherited
                            0,            // creation flags
                            NULL,         // use parent's environment
                            NULL,         // use parent's current directory
                            &siStartInfo, // STARTUPINFOW pointer
                            &piProcInfo); // receives PROCESS_INFORMATION

which "uses parent's environment" i.e. no custom environment variable support.

I'll work on a pull-request to get the functionality on par with *nix.

example to get stdout and stderr while process is running

Hello,

Can we have an example to get outputs of the child process in a loop while the child process is still alive. Consider that the child is going to run for a while. Also I need to terminate the child when the parent process is being killed. Is it possible?

Using poll() changes the return code

#include "subprocess.hpp"

using namespace subprocess;

int main() {
  std::vector<std::string> flags = {"ls", "nosuchfile"};
  std::string command = subprocess::util::join(flags);
  auto p = subprocess::Popen(command);
  // while (p.poll() == -1) {
  //   usleep(100 * 1000);
  // }

  p.wait();

  std::cout << "result " << p.retcode() << std::endl;
}

Outputs result: -1

While the below outputs result: 0.

#include "subprocess.hpp"

using namespace subprocess;

int main() {
  std::vector<std::string> flags = {"ls", "nosuchfile"};
  std::string command = subprocess::util::join(flags);
  auto p = subprocess::Popen(command);
  while (p.poll() == -1) {
    usleep(100 * 1000);
  }

  // p.wait();

  std::cout << "result " << p.retcode() << std::endl;
}

a bug in util::read_all() function

#23
there was a bug in util::read_all() function where it returned invalid data
template <typename Buffer> static inline int read_all(int fd, Buffer& buf)
and i don't know why the function is templated as it's dealing with a vector<char> and it's always called with a vector<char> correct me if i am wrong but anyways i changed it :D.
and we need an api of getting stdout content from a subprocess like what the test case is doing.

Support CPM / cmake

CPM is a lightweight "package manager" for C++/CMake projects.

It's mostly a convenience around CMake FetchContent.

It would be nice to allow this project to be consumed in such a way, which means that the CMakeLists.txt file needs to expose the header as a CMake consumable project for other projects/IDEs to cleanly consume and reference to.

If it is OK, I will submit a simple PR that resolves this.

some functions are not inline

Some functions are not inline. This will cause multiple definition errors in projects that include your lib.
Examples:

  std::string get_last_error()
  FILE *file_from_handle(HANDLE h, const char *mode)
void configure_pipe(HANDLE* read_handle, HANDLE* write_handle, HANDLE* child_handle)

There is already an issue #34, but it is about a specific function and you have a more general problem.

static inline functions in a header only library

You have a lot of static inline functions, such as

  static inline std::vector<std::string>
split(const std::string& str, const std::string& delims=" \t")

The problem is, with static functions, the compiler will create a separate internal copy of the function in every translation unit that has included subprocess.hpp. In large projects this can grow to huge numbers.
Those functions should be just inline, without static. This way they will be visible to the linker, so it will remove the copies.

Thread safety?

Hello,

When running multiple subprocess-instances in different threads simultaneously, the program sometimes crashes into "bad file descriptor" when writing into the subprocess pipe.

I will try to add manual thread safety to my program (so that only one thread can use subprocess at a time), just to be sure that this is indeed the cause of the problem. But should the library be thread-safe?

Cannot access process retcode after `communicate()`

It seems that only Popen::poll() sets Popen::retcode_ (which can be retrieved using Popen::retcode()), but Popen::communicate() instead calls Popen::wait() and throws away the result. I tried calling Popen::poll() myself, but it seems that just returns 0 (IIRC waitpid will only work once).

A simple fix seems to be to let communicate() do retcode_ = wait();, which works, but I'm not sure if that's the best approach here (perhaps wait() should just set it?).

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

#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.

bug in util::join

The current definition is

  static inline
  std::string join(const std::vector<std::string>& vec,
                   const std::string& sep = " ")
  {
    std::string res;
    for (auto& elem : vec) res.append(elem + sep);
    res.erase(--res.end());
    return res;
  }

It assumes that the separator is exactly 1 character, which doesn't have to be the case because the sep argument is a string.
Specifically this line is buggy:

    res.erase(--res.end());

Simple stderr example

Hi,

I'm looking for a way to collect only stderr from a subprocess, can you provide such an example please?

design of Popen arguments promotes unsafe use

This is a design issue. Basically there is a problem with definitions like this:

struct output
{
  output(int fd): wr_ch_(fd) {}

  output (FILE* fp):output(fileno(fp)) { assert(fp); }

  output(const char* filename) {
    int fd = open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
    if (fd == -1) throw OSError("File not found: ", errno);
    wr_ch_ = fd;
}
(...)

The problem is that output is not a RAII type that will close the file if not used, but rather a thin wrapper. This is not good for a type that is just a syntactic sugar for parameter passing. The thing is the user will expect to be able to prepare the arguments before the Popen call. If they are prepared but the Popen call is missed, this will leave dangling file handles.
Imagine code like this:

output o;
if(file_given)
    o = output{file_name};
if(condition)
{
    auto p = Popen({ "grep", "f" }, o, input{ PIPE });
    (...)
}

If condition fails, the code will leave a dangling open file.
The solution is to avoid opening files in the Popen argument types, and just store the filenames in them. The actual file opening should be done by Popen itself. Alternatively, there could be a RAII solution here, but it doesn't look as clean (it isn't needed to open the files until the actual Popen call is made).

Busy looping when waiting for subprocess to finish

Hi,

I just noticed that my program is busy-looping and thus using up a lot of CPU resources while waiting for a subprocess to finish. I'm using the Popen class. The root cause seems to be that waitpid() is used with the WNOHANG option in the util::wait_for_child_exit(int pid) function.

Why is WNOHANG being used? Is there a way to avoid busy-looping while waiting for a subprocess to finish?

Popen blocking on Windows

On Windows, the call to std::async in execute_process blocks until the process dies naturally, which is problematic if the process does not die and the intended use case is to kill it ourselves.
Could be easily fixed by storing the return value (of type std::future) of the call to std::async as an instance member. This way, the wait on the future would only happen when the instance is destroyed.
This:

  this->cleanup_future_ = std::async(std::launch::async, [this] {
    WaitForSingleObject(this->process_handle_, INFINITE);

    CloseHandle(this->stream_.g_hChildStd_ERR_Wr);
    CloseHandle(this->stream_.g_hChildStd_OUT_Wr);
    CloseHandle(this->stream_.g_hChildStd_IN_Rd);
  });

instead of this:

  std::async(std::launch::async, [this] {
    WaitForSingleObject(this->process_handle_, INFINITE);

    CloseHandle(this->stream_.g_hChildStd_ERR_Wr);
    CloseHandle(this->stream_.g_hChildStd_OUT_Wr);
    CloseHandle(this->stream_.g_hChildStd_IN_Rd);
  });

Reading from a pipe is messed up

I tried reading output from stderr from a process, and it gets all messed up. It seems the length of the buffer returned is correct, but only the first couple of hundred bytes are filled, the rest are zeroes.

Looking at the code, it seems that read_atmost_n does not handle partial reads correctly. Changing this line to the following seems to fix this.

int read_bytes = read(fd, buf + rbytes, read_upto - rbytes)

On a related note, I suspect that if read_all resizes the buffer and causes a realloc, then the buffer variable might become invalid.

Compare with similar/related libraries

First - thank you for this effort. I just noticed the repository...

I was wondering what the pros and cons of cpp-subprocess are relative to other C++ libraries regarding process management, piping and such. I remember that Boost has something like this... ah, yes: Boost::Process; and perhaps there still other options.

It would be useful if you could compare and contrast your library with these alternatives, to help users decide what's a better fit for them. Remember that many/most C++ developers don't have experience with Python 2.7's subprocess facilities/library, so we don't automatically know what's offered.

This would fit nicely inside the README, or possibly a Wiki page here on GitHub with a link from the README.

Segfault when creating and closing lots of subprocesses

This behavior is seen in 126ee29.

Steps to reproduce

Compile and run the following program on a non-Windows system:

#include <iostream>
#include "subprocess.hpp"
using namespace subprocess;

int main(int argc, char **argv) {
    for (int i=0; i<1000; i++) {
        std::cout << i << std::endl;
        auto p = Popen({"grep", "f"}, output{PIPE}, input{PIPE});
        auto msg = "one\ntwo\nthree\nfour\nfive\n";
        p.send(msg, strlen(msg));
        auto res = p.communicate();
    }
}

Expected behavior

The program runs for 1000 iterations and exits.

Actual behavior

The program runs for some iterations and segfaults. The number of iterations changes as ulimit -n is changed.

Likely cause

Running lsof at the end shows that only six file descriptors are open. However, if file descriptor is made accessible via a FILE * via fdopen, it's necessary to close it with fclose. The orphaned file descriptor won't show up in lsof but it will count against the limit.

Fix all the compilation warnings

Hi,

There are quite many compilation warnings, it'd be nice if they were ironed out (e.g. unsigned/signed comparison, unused parameters).

Thanks.

`Test::test_buffer_growth_threaded_comm` is throwing errors

When I compile test_cat and run it, I get the following error:

$ cd test
$ g++ -Wall -lpthread -o test_env test_env.cc
...
$ ./test_env
Test::test_cat_pipe_redirection
END_TEST
Test::test_cat_file_redirection
END_TEST
20480
free(): invalid next size (normal)

Conan support

Will conan support be beneficial for the project?

I understand this is header-only, but sometimes it's more convenient to just use conan as if it was reguar project.

I'll be happy to open PR if that's beneficial.

Child process does not exit in case of execve failure

Consider the following code:

#include "subprocess.hpp"

int main() {
    try {
        auto p = subprocess::Popen({"nonexistent-binary"});
        p.wait()

    } catch (const std::runtime_error& e) {
        std::cout << "exception triggered: " << e.what() << std::endl;
    }

    return 0;
}

When running this, it will print an exception message twice:

$ make test
g++ -g -std=c++17 -o subprocess main.cpp -pthread
./subprocess
exception triggered: execve failed : No such file or directory
exception triggered: execve failed : No such file or directory

The exception appears to be thrown in both the parent and the child process in case of execve failure. This seems like a bug as a result of not exiting the forked process.

execute_child shouldn't use any signal-unsafe functions

I see the uses of std::string and setenv after fork. I believe these functions are unsafe, because after fork, the state of memory heap is undefined. I haven't been able to produce crash myself so this issue isn't super critical, but it'd be good to fix them.

For setenv, perhaps we should create a new environ before fork in the parent. For std::string, we can just write a raw string using write(2) and call _exit.

Popen fails to return error code in shell mode

I would expect this code:

    using namespace subprocess;
    auto proc = Popen("ls fdklajfdlsajfdkljaf", error{PIPE}, cwd{where}, shell{true});
    auto errors = proc.communicate().first;
    std::cerr << errors.buf.data() << std::endl;
    int exit_code = proc.wait();
    if(exit_code != 0)
    {
        cerr << "the command " << command << " returned error code " << exit_code << endl;
        exit(1);
    }

to set the exit_code variable to 2 and exit. Instead it sets it to 0 and goes on.

readme minor missing content

I think we missed output(pipe) in the constructor of Popen in the detailed way of example 1 in file readme.md.

Best,
Aimin

Multiple definition Error

My code is set up as follows:

main.h

#include "helper.h"

helper.h

#include "subprocess.hpp"

helper.cpp

#include "helper.h"

Error:


Because of this, I get:

main.cpp.o: In function std::iterator_traits<unsigned char const*>::iterator_category std::__iterator_category<unsigned char const*>(unsigned char const* const&)': subprocess.hpp:152: multiple definition of subprocess::util::quote_argument(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, bool)'
main.cpp.o:/subprocess.hpp:152: first defined here
helper.cpp.o: In function std::vector<char*, std::allocator<char*> >::reserve(unsigned int)': /subprocess.hpp:152: multiple definition of subprocess::util::quote_argument(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, bool)'
main.cpp.o:/subprocess.hpp:152: first defined here
collect2: error: ld returned 1 exit status

Solution


This is easily solved by changing void quote_argument(const std::wstring &argument, std::wstring &command_line, bool force) to inline void quote_argument(const std::wstring &argument, std::wstring &command_line, bool force)

* Filenames changed for privacy.

[Question] Why delete operator= for the Streams class?

Hi, thank you for writing such a useful package!

I'm trying to write a program where I store a copy of the Popen as a class attribute so that I can access the results at a later time. Right now when I try to assign it, I get an error that I cannot set the value because the assignment operator is deleted. I can work around it by storing the Popen instance in vector, but then I get a segfault when I try to extract the result later with communicate().first.buf().data() because I think perhaps the streams input/output are stored only by reference so go out of scope. Fun fact that it works on mac but segfaults on ubuntu, but I think it probably should segfault on both :)

Everything works as long as I do all Popen calls within the same function, but unfortunately I need to be able to store the Popen instance somewhere so that I can get the results later with communicate(). Do you know of any possible workaround? I would be happy to hear any advice you have and just modify my local copy of the library if you don't want to make any changes to the source.

wait() / communicate() can hang indefinitely with no recourse

The issue here is basically that there's no way to specify a timeout. I hacked the code myself with a new exception type, a global constant for timeout, and a few std::chrono calls in wait_for_child_exit(). However, my global constant probably isn't a great way to do this.

Why is this a problem?

Consider that you have a very important process which cannot crash or hang which needs to run a program that potentially behaves badly. If the other program does behave badly (monitored through pipes, i/o, etc), one would probably like to kill and print the stdout/stderr.

Now, presumably kill(9); communicate(); will always return quickly. But suppose it doesn't and your other program really is just deadlocked. Now your main program is going to hang and there's nothing you can do about it.

Visual C++ Support

Is there any support to VC++? If possible in future releases this support could be included and done tests?

is cpp-subprocess thread safe?

Or does it provide the option of thread safety?

In my code I'm using an openmp loop where I would like to call sp::Popen.

It looks something like this:

#pragma omp parallel for
for(size_t i = 0; i < v.size(); i++)
{
	auto p = Popen({"subprocess"}, input{PIPE});
	p.communicate(v[i].c_str(), v[i].size() + 1);
}

where v is a std::vector<std::string> but it hangs randomly at the fork() call in subprocess.hpp:1159

Thanks in advance and thanks for the amazing library.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.