From henrik.bengtsson at gmail.com  Wed Jan 25 22:42:47 2017
From: henrik.bengtsson at gmail.com (Henrik Bengtsson)
Date: Wed, 25 Jan 2017 13:42:47 -0800
Subject: [Rd] parallel::mc*: Is it possible for a child process to know
 it is a fork?
In-Reply-To: <CABFfbXu-VkzaGJqmkNUDk7GvXgF0T6SazukGFza9PSmozBs5fA@mail.gmail.com>
References: <CAFDcVCRtpGfSvUxyQKSoufWLCAeXVCTMpn6x9WFL9F1SJh68AA@mail.gmail.com>
	<CABFfbXu-VkzaGJqmkNUDk7GvXgF0T6SazukGFza9PSmozBs5fA@mail.gmail.com>
Message-ID: <CAFDcVCQLgv3At278h7E2CLAd2qttsaUHTq2cMMwMPACEWtANKg@mail.gmail.com>

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



[Rd] parallel::mc*: Is it possible for a child process to know it is a fork?
Henrik Bengtsson