Giter VIP home page Giter VIP logo

boost-process's Introduction

boost-process's People

Contributors

borisschaeling 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

Watchers

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

boost-process's Issues

Potential bug in async wait process example

In boost-process/libs/process/example/wait.cpp:52 , the class boost::asio::windows::object_handle is used with the child process handle.
I think CloseHandle() will be called twice with the same process handle in the destructors of boost::process::child and boost::asio::windows::object_handle.

DuplicateHandle() can be used to avoid the problem:

#if defined(BOOST_WINDOWS_API)
    DWORD exit_code;
    HANDLE dupHandle;
    DuplicateHandle(GetCurrentProcess(),c.process_handle(),GetCurrentProcess(),&dupHandle,
                    0,false,DUPLICATE_SAME_ACCESS));
    boost::asio::windows::object_handle handle(io_service, dupHandle);
    handle.async_wait(
        [&handle, &exit_code](const boost::system::error_code&)
            { ::GetExitCodeProcess(handle.native(), &exit_code); }
    );
#endif

Unportable string handling in API

The way char vs wchar_t strings are handled on Windows makes hard to write portable code. Currently, if UNICODE is defined the API is wide and if not it is narrow. On POSIX it is always narrow.

The only way to write portable code with this API is to use the preprocessor to select completely separate implementations based on #ifdef UNICODE.

Instead both narrow and wide versions should always be defined and it is up to the caller which they use.

The problem did not exist in previous versions of Boost.Process.

Avoid inclusion of <windows.h>

Briefly looking through the source code I've noticed that at least one its header file includes windows.h. This file has always been a nightmare as it spoils global namespace with lots of macro definitions with unprefixed names which are likely to clash. It's not the the way like modern C++ deals with things.

The only one way windows.h could be reliably hidden is putting it in a source file, not a header. I know that after this you cannot call the library header only, but to me this really makes sense for code sanity.

Confusing docs for set_args

The docs for set_args say 'The first argument specifies the executable to start unless run_exe is used'. It's not clear from this if the first argument you pass is argv[0] or argv[1] when also using run_exe.

It turns out on Windows that the first argument in argv[0], rather than what you passed to run_exe. It looks like this is different from the POSIX behaviour:

    explicit run_exe_(const std::string &s) : s_(s), cmd_line_(new char*[2])
    {
        cmd_line_[0] = const_cast<char*>(s_.c_str());
        cmd_line_[1] = 0;
    }

Status?

Hey Boris,
I was trying to trace the status of the project and couldn't really figure out where things stand. What are the open issues that need to be resolved before another boost review can be done?

Solaris compilation

Hi,

To compile with Solaris, the following patch would be needed:

Index: boost/process/posix/initializers/inherit_env.hpp
===================================================================
--- boost/process/posix/initializers/inherit_env.hpp       (revision 262831)
+++ boost/process/posix/initializers/inherit_env.hpp    (working copy)
@@ -17,6 +17,10 @@
#   define environ (*_NSGetEnviron())
#else
#   include <unistd.h>
+extern "C"
+{
+    extern char **environ;
+}
#endif
 namespace boost { namespace process { namespace posix { namespace initializers {

Regards,
Daniel.

Argument handling is not transparent on Windows

When arguments contain quotes on Windows, they are not passed to the program correctly because the argument handling in Boost.Process 0.5 is naive. Currently, it just checks to see if an argument has a space in it and, if so, surround the argument with quotations. This breaks if the argument itself contains quotations.

The previous version of Boost.Process did not have this problem.

Keep child alive when parent application terminates

Howdy. I am using Boost Process to run a child process (command called DreamDaemon, game server) from a parent C++ application, obviously. I was wondering if there was a way to keep the child DreamDaemon process when my C++ application closes.

e.g. I run the following code:

child child = execute(set_args(argsChild), close_stdin());

With argsChild as my command line arguments

DreamDaemon will start up, and the game will start. However, if I terminate my own application (control+c), it kills the DreamDaemon instance with it. Not entirely sure if this is making sense, so if you can't follow, I'll try to explain it another way.

Is it possible to keep the DreamDaemon process running even when my parent app is closed? I would have thought that since I just execute the command, it is hands off? Does this have something to do with the child object being killed when my application is terminated? Any info you can give would be appreciated, thanks!

Virtualise initializers

First of all, thanks for the good work here, the API is very clean, and yet extensible and practical, which is a good thing when trying to abstract something so different across OSes.

However, I don't fully understand why the code is so much static. Why did you choose to use compile time polymorphism (i.e. templates) instead of runtime polymorphism (i.e. vtables) ? IMHO the overhead of spawning a process makes the cost of a vtable access ridiculous.

My problem, somewhat related to the previous question, is how to create a set of initializers, and then spawn a process. I would like to do something like:

std::vector<Initializer> initializers;
if (some_condition)
    initializers.push_back(some_initializer);
auto child = boost::process::executor()(args, initializers);

In order to create the type Initializer, I would have to do complicated things:

template<typename Executor>
struct InitializerBase
{
      virtual void on_fork_setup(Executor& e) = 0;
     // ... other methods here
};

template<typename Executor, typename ConcreteInitializer>
struct InitializerWrapper : InitializerBase<Executor>
{
    ConcreteInitializer _initializer;
    template<typename... Args
    explicit InitializerWrapper(Args&&... args)
        : _initializer(std::forward<Args>(args)...)
    {}
    void on_fork_setup(Executor& e) override { _initializer.on_fork_setup(e); }
     // ... other methods here
};

template<typename Executor>
struct _Initializer
{
    typedef Executor executor_type;
    std::unique_ptr<InitializerBase> _initializer;
    void on_fork_setup(Executor& e) { _initializer.on_fork_setup(e); }
   // ... other methods here
}

#ifdef POSIX_SOMETHING
typedef _Initializer<PosixExecutor> Initializer;
#else
// something else
#endif

template<typename ConcreteInitializer, typename... Args>
Initializer make_initializer(Args&&... args)
{
  return Initializer(new InitializerWrapper<typename Initializer::executor_type, ConcreteInitializer>(
     std::forward<Args>(args)...);
}

(I omitted the boilerplate code for constructors and destructors)

That's pretty much re-virtualizing your code ... Do you know a better way ?

wrong CreateProcess call

I want to call the executable svn which is defined in my PATH environment variable with some arguments. I've used set_args instead of run_exe. The execute call fails, boost-process creates a wrong CreateProcess call.

std::vector<std::string> const args = { "svn", "propget", "-R", "svn:externals"};
using namespace boost;
system::error_code ec;
process::execute(process::set_args(args), process::set_on_error(ec));

See CreateProcess

If lpApplicationName is NULL, the first white space–delimited token of the command line specifies the module name. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin (see the explanation for the lpApplicationName parameter). If the file name does not contain an extension, .exe is appended. Therefore, if the file name extension is .com, this parameter must include the .com extension. If the file name ends in a period (.) with no extension, or if the file name contains a path, .exe is not appended. If the file name does not contain a directory path, the system searches for the executable file in the following sequence:

The directory from which the application loaded.
The current directory for the parent process.
The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The directories that are listed in the PATH environment variable. Note that this function does not search the per-application path specified by the App Paths registry key. To include this per-application path in the search sequence, use the ShellExecute function.

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.