Boost logo

Boost :

Subject: Re: [boost] Boost.Process article: Tutorial and request for comments
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2009-04-21 17:21:14


Hi,

Excellent idea to write this article.

I have not used the library neither read the documentation deply.

I have however some suggestion about the library design.

I don't see the need to separate between several specific platform classes.
A program using the Proces library will run only with one platform available, so classes as process and child could include conditionaly the specific features. The current design has the advantage of making explicit the non portable parts, but how do you provide features common to two platforms that are not available to a third one? In addition the risk to make specific classes would be that the underlying concepts are too close to the concrete feautures provided by one platform. I would prefer to have a specific define for each non portable feature.

I will organize the specific classes on a specific platform namespace
common for the portable part

namespace process {
namespace common {
    class process;
    class child;
}

posix for the posix based OS

#ifdef BOOST_PLATFORM_POSIX // or something like
namespace process {
namespace posix {
    class process : public common::process{...};
    class child: public common::child{...};
}
}
#endif

window for the micosoft OS based platforms

#ifdef BOOST_PLATFORM_WINDOWS // or something like
namespace process {
namespace windows {
    class process : public common::process{...};
    class child: public common::child{...};
}
}
#endif

// other platforms

and have typedef or a using directive at the namespace process level for each one of the available classes as

namespace process {
#if defined(__POSIX__) // or something like
typedef posix::process process;
// or using posix::process;
#elsif defined() // other patforms
...
#else
typedef common::process process;
or // using common::process;
#endif
}

When the user use a non portable feature on a portable programm it will need to check conditionally for the non portable feature as

#ifdef BOOST_PROCESS_HAS_SPECIFC_FEATURE_1
// ...
#else
// ...
#endif

Your proposal about iterating over all the process working on a machine is a must to have.

The issue respect to the map environement could be abstracted by defining a specific class that manage the synchronization between the settings and the collection.

Even if the following could be done in a higher library (Shell), I would like to think about the context concept as a shell which can be nested and have a stack of shells. This stack can be stored on a thread specific context, so when a new process is created it will inherit from the current context.

In the shell context a command could find a place. For example,
    
    shell::cd("/tmp");

will change the current directory to "/tmp" on the top context of the stack..

If the command fails it can be recovered

Commands could be composed using pipe "|",
    shell::cat("/tmp.file.txt") | shell::wc();

redirection ">"

    shell::cat("/tmp.file.txt") | shell::wc() > str;

tee

    shell::cat("/tmp.file.txt") | shell::grep () | shell::tee("file");

conditional concatenation "&",

    shell::cd("/tmp") & shell::ls();

which executes ls only if cd /tmp succeeds.

Portability is not only related to the platform features, but also about the features provided by specific programs. I would like to see an example of how the user would write portable code when he wants to execute a program that has different syntax on different platforms but provides the same feature, e.g the equivalent of "ping" on solaris id "ping -c 1" on linux.

Last some minor questions:
What about renaming handle by native_handle?
What is wrong on using the Boost.Filesystem library to idientify executables?
Why the do we need to duplicate the name of the executables as an argument?
Respect to relative or absolute path of executables,why not let the undelying platform to handle with this?

HTH,
Vicente

----- Original Message -----
From: "Boris Schaeling" <boris_at_[hidden]>
To: <boost_at_[hidden]>
Cc: <boost-users_at_[hidden]>
Sent: Tuesday, April 21, 2009 2:01 PM
Subject: [boost] Boost.Process article: Tutorial and request for comments

>
> I've written an article about Boost.Process:
> http://www.highscore.de/cpp/process/
>
> I've also fixed a few bugs in Boost.Process (which is now 0.31):
> http://www.highscore.de/boost/process.zip
>
> And the latest source code can also be found in the sandbox:
> https://svn.boost.org/svn/boost/sandbox/process/
>
> For developers not familar with Boost.Process the article is a tutorial to
> get more easily started. For developers familiar with Boost.Process it is
> a request for comments.
>
> I've been looking at the big picture finally trying to find out where and
> how Boost.Process should be changed and in which direction it should move
> to become a complete library one day. As not everyone will read the entire
> article here are my thoughts:
>
> 1) Boost.Process is based on a few concepts like 'process' and 'context'.
> While those make sense there are other concepts where I wonder if they
> should be dropped:
>
> * 'executable' is the executable name which in practice must be a
> std::string. I think the original idea was to support numerous string
> types. This leads to the question how to support different Unicode
> encodings which I think is still unanswered in the Boost community. Other
> libraries, eg. Boost.Interprocess, simply stick to one string type
> (typically std::string).
>
> * 'handle' is the underlying native file handle of a stream (file
> descriptor on POSIX systems, handle on Windows). The concept is based on a
> class in the detail namespace of Boost.Process. There is just one class
> and it's not meant to be used by users of the library either. Thus I'm not
> sure what's the benefit of having an explicit 'handle' concept at all.
>
> 2) Environment variables must be sorted on Windows but not on POSIX
> systems. On Windows the type environment could be a typedef for std::map
> and on POSIX systems for std::unordered_map. Currently it's always a
> typedef for std::map. Is that ok? Should it be changed? Should a macro be
> provided in case developers want to use different typedefs?
>
> 3) Currently Boost.Process is really only useful for creating child
> processes. It's not possible for example to detect and iterate over other
> processes on a system. I guess Boost.Process should be enhanced here. Then
> one day the well-known utility 'ps' on POSIX systems could be implemented
> in Boost C++. Any comments?
>
> 4) When a process is created the standard streams (stdin, stdout and
> stderr) are closed by default. Is this a good choice? If it isn't what
> should happen otherwise? Inherting standard streams (which is the default
> behavior with fork on POSIX systems)?
>
> 5) Boost.Process requires to specify an absolute path to an executable
> which should be started. There is a helper function which returns the
> absolute path for an executable name (it uses the environment variable
> PATH). The question is if this should be done automatically if no absolute
> path is given?
>
> 6) When a stream of a child process is captured Boost.Process
> automatically creates a pipe. As pipes don't support asynchronous
> operations on Windows a named pipe is required (called FIFO on POSIX
> systems). Currently a macro must be defined to make Boost.Process use a
> named pipe on Windows. It might make more sense to enable developers to
> choose either a pipe or a FIFO explicitly - not only on Windows but on
> all platforms. Any comments?
>
> 7) It's possible to capture and access streams of a child process. Those
> streams are derived from std::istream and std::ostream and thus only
> support blocking I/O operations. Currently the underlying handle has to be
> fetched to initialize a generic I/O object from Boost.Asio to use
> asynchronous I/O operations. How should the library be changed to make it
> easier to use asynchronous I/O?
>
> 8) There is a method wait() which makes it possible to wait for another
> process to exit. Currently wait() is provided by the class child though.
> Shouldn't it really be defined by the class process (so you can wait not
> only for child processes to exit)?
>
> 9) As wait() blocks an asynchronous alternative should be provided.
>
> 10) The Windows-specific classes all start with win32_ (eg. win32_child).
> Wouldn't it make more sense to use windows_ instead (like windows_child)
> or a windows namespace? First other libraries use windows_ (see
> Boost.Interprocess). Second there should be no reason why a class like
> win32_child can't be used on a 64-bit Windows.
>
> Boris
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk