Thanks for all of your help and pointers so far — I'm close to getting things fully working, but I've found it a little cumbersome to create an StdChildWrapper that doesn't overwrite all of the methods of things like JobObjectWrapper.
My wrapper looks like this:
#[derive(Debug)]
struct LogFileChild {
inner: Box<dyn StdChildWrapper>,
thread: Option<JoinHandle<io::Result<u64>>>,
}
And the solution is to (I believe) manually implement all of the default methods that either of my other wrappers (JobObject or CreationFlags) use, and change the default implementation from something like self.inner_mut().kill() to self.inner.kill(). This is obviously non-ideal, because:
- I need to dig into the source-code of
process-wrap to figure out which methods I need to manually implement / change from self.inner_mut() to self.inner, something of a SemVer nightmare (unless I just manually implement every single method).
- It, I believe, introduces more order-dependent behavior — if I put my wrapper before
JobObject, for example, then any changes I make to a method that JobObjectChild doesn't re-implement / forward would be lost. If I wrote something for id() or stdout(), it would be completely and silently discarded.
I think that, conceptually, what's needed is to change the Child in the return types of inner(), inner_mut(), and into_inner() into something like Box<dyn StdChildWrapper> — that way, by default, all of the unimplemented methods would retain the previous wrappers! If this is something you think is a fundamentally good idea, then I'm happy to brainstorm about the implementation (e.g. should this really be a Box<dyn...>, or should it be a generic trait, or one with an associated type, etc).
Currently, I believe, any new ChildWrapper with any methods left default is wiping the effects of all of the previous wrappers, and that feels like a pretty major footgun that makes it challenging to build new wrapper combinations, but I love this library so much that I'd love to help fix that!
Thanks for all of your help and pointers so far — I'm close to getting things fully working, but I've found it a little cumbersome to create an
StdChildWrapperthat doesn't overwrite all of the methods of things likeJobObjectWrapper.My wrapper looks like this:
And the solution is to (I believe) manually implement all of the default methods that either of my other wrappers (
JobObjectorCreationFlags) use, and change the default implementation from something likeself.inner_mut().kill()toself.inner.kill(). This is obviously non-ideal, because:process-wrapto figure out which methods I need to manually implement / change fromself.inner_mut()toself.inner, something of a SemVer nightmare (unless I just manually implement every single method).JobObject, for example, then any changes I make to a method thatJobObjectChilddoesn't re-implement / forward would be lost. If I wrote something forid()orstdout(), it would be completely and silently discarded.I think that, conceptually, what's needed is to change the
Childin the return types ofinner(),inner_mut(), andinto_inner()into something likeBox<dyn StdChildWrapper>— that way, by default, all of the unimplemented methods would retain the previous wrappers! If this is something you think is a fundamentally good idea, then I'm happy to brainstorm about the implementation (e.g. should this really be aBox<dyn...>, or should it be a generic trait, or one with an associated type, etc).Currently, I believe, any new
ChildWrapperwith any methods left default is wiping the effects of all of the previous wrappers, and that feels like a pretty major footgun that makes it challenging to build new wrapper combinations, but I love this library so much that I'd love to help fix that!