Background
A while ago I wrote a Raku
module to test out some ideas I had for making external process pipelines (e.g., grep raku | wc -l
). I followed the traditional way of creating Pipes
and setting up I/O
redirections for the external processes.
Since there's no fork
available in Raku
, nor is it recommended due to threads in MoarVM
, I resorted to using Proc::Async
to start a wrapper process for each external command in a pipeline, and the wrapper would then sets up I/O
redirections to connect the command processes and the pipes, and then close other FDs before exec
-ing the real command.
Problem
This all seems to work well except there's still the possibility that other parts of the program using the module might start a sub process (e.g., via run
, shell
, Proc
, or Proc::Async
) in another thread after the pipe FDs
are created but before they are closed, thus leaking them and causing the command processes in the pipeline to block on read / write
.
Question
How would you prevent FDs
from leaking to any child processes started in another thread in Raku
?
Thanks
OO::Monitors
to wrap the filehandles to prevent other threads from using it at the same time? – GailyOO::Monitors
prevents multiple threads from entering a method of an instance of that class at the same time. In my case, I have no control over what other parts of the system do; a program could be using some module that starts a thread that runs an external program viaProc::Async
periodically, and I'll have no control over that. – Whosoeverrun
,shell
,Proc
andProc::Async
to make them acquire a lock that my module acquires for the critical section, assuming those are the only entrypoints in Raku that would create sub processes. – Whosoeverfork
the Raku process is problematic to begin with, I wouldn't worry about it too much. I suspect monkey-patchingProc::Async
might be enough. – Whosoeverfork
available in Raku, nor is it recommended due to threads in MoarVM". I'm not disagreeing, but are you aware that this works?:use nqp; my $i = nqp::fork(); say $i;
. See A future for fork(2). – Autocratfork
vianqp
. I suppose it takes care of any problems one might have with calling the OSfork
via nativecall? If so, then I might be able to use it to replace the hack of usingProc::Async
+ nativecallexec
with justnqp::fork
+ nativecallexec
. Thanks for bringing this to my attention! – Whosoeverfork
via nativecall?" No. I urge you to read the article and contact Bart Wiegmans. His approach relies on ensuring there's only one system thread in use at the time thefork
occurs: "force MoarVM into a single active thread even with multiple user threads active". However "that still leaves cleanup to deal with, after returning fromfork()
in the child process. Also, this will not work if a thread is blocked on NativeCall." Also: "abusing the GC in order to enable afork()
may be a bit over the edge of insanity :-)". – Autocrat