Boost logo

Boost :

Subject: Re: [boost] [gsoc] Boost.Process done
From: Boris Schaeling (boris_at_[hidden])
Date: 2010-09-08 17:20:01


On Wed, 08 Sep 2010 03:37:52 +0200, Ilya Sokolov <ilyasokol_at_[hidden]>
wrote:

> [...]
>> I'd appreciate if you could comment on the changes. Especially have a
>> look at:
>>
>> * this signature: std::pair<handle, handle> (bool).
>
> It would be better if delegate would accept fileno instead of bool
> indicating input/output. bp::behavior::inherit seems almost
> indistinguishable from the redirect_to.

Which fileno should be passed? stdin/stdout/stderr of the parent process?

Maybe we have a similar idea because I also think it would be better to
distinguish standard output and standard error. This could be done with an
enumeration and could maybe help to create a better redirect_to stream
behavior. The problem with redirect_to though is that it depends on
another stream behavior. I don't know whether Boost.Process should support
dependencies between stream behaviors? Here is some pseudocode which could
work somehow:

----------
enum stream_type { in, out, err };

class redirect_to
{
public:
   redirect_to(stream_type to)
   : to_(to)
   {
   }

   // delegate gets reference to context object to access
   // other stream behaviors
   pair<handle, handle> operator()(stream_type st, context &ctx) const
   {
     if (to_ == out && st == err)
     {
       // init_stdout_behavior() calls stdout_behavior() with correct
       // parameters and caches handles
       handle child_stdout = ctx.init_stdout_behavior().first;
       return make_pair(child_stdout, handle());
     }
     else if
       ...
   }

private:
   stream_type to_;
};

context ctx;
ctx.stdout_behavior = pipe();
ctx.stderr_behavior = redirect_to(out);
----------

init_stdout_behavior() would need to make sure that stream behaviors are
initialized only once (not that there are multiple pipes created). But
then it's difficult again to reuse a context object as it would need to be
reset explicitly. But this could be done in create_child() again. -
Comments?

>> What still has to be done?
>>
>> * The context class still has a default constructor only which
>> initializes the stream behaviors to inherit standard streams. This is a
>> problem for Windows GUI applications as they don't have standard
>> streams (or at least they are closed). While the Named Constructor
>> Idiom has been proposed what exactly should the done? Should the
>> default constructor be private and developers must explicitly use a
>> factory function to create a context object? Shall the factory function
>> initialize all standard streams with the same behavior? Shall we
>> provide a factory function which expects three parameters to initialize
>> the standard streams? What's convenient and flexible and not too
>> confusing?
>
> I expect that if some std stream is closed in the calling process,
> the default constructor of the context class doesn't throw anything.
> As I see it, the bp::handle should have a "dont-close" flag and
> bp::behavior::inherit shouldn't call dup() or DuplicateHandle().

The reason why bp::behavior::inherit calls dup()/DuplicateHandle() is that
a parent closes a child's handles (and a child a parent's handles; this is
done in create_child()). Otherwise both processes would have a read and
write end open when a pipe is used. Without a dup()/DuplicateHandle() a
parent would close its own standard streams if it wants the child to
inherit them. I think it also makes logical sense to automatically close
the streams of the other process?

As I also think the default constructor of context shouldn't throw: What
if we add another optional parameter to bp::behavior::inherit? A bool
variable could be used to indicate whether bp::behavior::inherit should
throw if dup()/DuplicateHandle() fails. By default it throws - but it
doesn't when used by the default constructor of context?

Anyway, enough ideas for now. :)

Boris


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