
On Sat, 18 Aug 2012 23:54:24 +0200, Roland Bock <rbock@eudoxos.de> wrote: Hi Roland,
[...]But things like wait_for_exit seem strange to me: If the library takes care of the forking and handles setting up pipes in such a nice way, why should the user of the library be bothered with the different ways of interpreting the exit information (unless he really, really wants to)?
can you show me some sample code how you'd like to interpret the exit code?
Same with a /dev/null sink. Offering a factory method would be easy and spares the user.
I think this is a Boost.Iostreams problem. We have a null device in Boost.Iostreams (see <http://www.boost.org/doc/libs/1_50_0/libs/iostreams/doc/classes/null.html>) but it's a class with no-op functions. If the class would open /dev/null or NUL, one could use the null device. What I can do for now is changing the example in the Boost.Process documentation. Instead of writing to /dev/null or NUL, it should write to foo.txt - problem solved. ;)
[...]I understand that the signal stuff is not required for Windows, but why not offer a convenience function that sets the signal handler on POSIX and does nothing on Windows?
Same with the discard method. Does something on Windows, does nothing on POSIX, and I get to write code without using the #ifdefs every other line.
I'm afraid it leads to code obfuscation if you have a superset of all existing functions platforms provide and they are all used together in the same code with no clear indication which ones do something useful and which ones are no-ops. Imagine you had no-op Windows API functions and no-op POSIX API functions. You could use all system API functions from Windows and POSIX without #ifdefs in the same source file and claim your code is platform-indepedent. But I think I wouldn't call it platform-independent but a complete mess. ;) It is maybe no problem for the example you are referring to as we are talking only about two lines here. But we start trading convenience vs. clarity? And if you call discard() and think you are fine on all platforms, you'd make a mistake?
The other thing about the discard: I think one of the first things I'd do is write a wrapper for child that is non-copyable (as also suggested by Joel) and calls discard in its destructor. I wonder if that should not be part of the library, too?
This is related to the paragraph above. The RAII type would only make sense on Windows but the code would compile on all platforms. If you don't know that you must do something extra on POSIX (like ignoring SIGCHLD), your program will leak resources (leaking is maybe the wrong word as init will clean up after the program exits; but you might be tricked into thinking the platform-independent RAII type does something for you on all platforms which wouldn't be true).
With the probable exception of the asynchronous IO and wait, I think it should be possible to get rid of the #ifdefs in the tutorial. And IMHO that would be a nice improvement for what looks like a cool library already :-)
Thanks! I mentioned it already in another email I think: If I rewrite some and remove other examples from the tutorial, most of the #ifdefs could disappear. Boost.Process would still support all of that (and I know anyway how to do all of that myself :). But it would make it more difficult for others as everyone would have to figure out himself how to do certain things like asynchronous I/O. I agree that the best solution would still be to support everything with truly platform-independent classes and functions. But I think that some problems have be solved in Boost.Asio (posix::stream_descriptor vs. windows::stream_handle) or Boost.Iostreams (/dev/null vs. NUL) and that other problems are a bit more complicated that it's not clear at all how to solve them in a platform-independent way (signals vs. wait functions)? Boris
[...]