parallel::mc*: Is it possible for a child process to know it is a fork?
On Tue, Jan 24, 2017 at 8:10 PM, Jeroen Ooms <jeroenooms at gmail.com> wrote:
On Tue, Jan 24, 2017 at 7:06 PM, Henrik Bengtsson <henrik.bengtsson at gmail.com> wrote:
When using multicore-forking of the parallel package, is it possible for a child process to know that it is a fork?
R internally uses R_isForkedChild to prevent certain operations within
the fork. However I don't think this is exported anywhere. You could
do something like:
extern Rboolean R_isForkedChild;
SEXP is_forked(){
return ScalarLogical(R_isForkedChild);
}
But that won't be allowed on CRAN:
* checking compiled code ... NOTE
Found non-API call to R: ?R_isForkedChild?
Compiled code should not call non-API entry points in R.
Yes, that's a bummer. It could be useful to have this exposed. It's
used by several core packages, not just 'parallel' itself;
$ grep -F R_isForkedChild -r --include="*.h"
src/include/Defn.h:extern Rboolean R_isForkedChild INI_as(FALSE); /*
was this forked? */
$ grep -F R_isForkedChild -r --include="*.c"
src/library/tcltk/src/tcltk_unix.c://extern Rboolean R_isForkedChild;
src/library/tcltk/src/tcltk_unix.c: if (!R_isForkedChild && !Tcl_lock
src/library/parallel/src/fork.c:#include <Defn.h> // for R_isForkedChild
src/library/parallel/src/fork.c: R_isForkedChild = 1;
src/modules/X11/devX11.c: while (!R_isForkedChild && displayOpen &&
XPending(display)) {
src/modules/X11/devX11.c: if(R_isForkedChild)
src/unix/sys-unix.c: if (ptr_R_ProcessEvents && !R_isForkedChild)
ptr_R_ProcessEvents();
Another method would be to look at getppid(2) and getpgid(2) to lookup the parent-id and group-id of the current process and test if it matches that of the (parent) R process.
I'm not 100% sure I follow. Is the idea similar to the following in R?
ppid <- Sys.getpid()
is_child <- parallel::mclapply(1:10, FUN = function(i) { Sys.getpid() != ppid })
How can the child process know 'ppid'? getppid would give the parent
PID for any process, which could be a non-R process.
If you are only interested in limiting further parallelization within the fork, perhaps you can simply use parallel::mcaffinity to restrict the forked process to a single core.
This is tied to parallelization via parallel::mc*, correct? That is, is it only parallel:::mcfork() that respects those settings or does this go down deeper in the OS such that it affects forking / threading on a more general level? Thanks for your pointers and suggestions, Henrik