On 16/06/2016 18:02, Klemens Morgenstern wrote:
Hi Klemens,
We have been using the Boost.Process state from Boris Schäling for more than 3 year in productive use on linux embedded devices, and one thing that we had to change is to use vfork instead of the fork function.
The problem with the fork + execve is that it produce a RAM copy of the process page, while vfork+execve just don't. And when the parent process launching child is pretty big, imagine a jvm using some jni library using Boost.Process... it duplicates the whole Jvm im RAM to then deallocate all at the moment of execve. vfork doesn't have this issue on linux.
Without the use of vfork, you end up in situations where you get the following error: `boost::process::detail::posix_start: fork(2) failed: Cannot allocate memory`
I think changing from fork to vfork is not much and brings alot of advantages, but one must be aware that at_fork handler won't be called. But this is not important as fork is used to do execve afterwards in Boost.Process. Hi Damien,
I appreciate your problem, but I am not sure it's that easy. There's on major problem: vfork is removed from the posix standard as of POSIX.1-2008. And I'm trying to conform to posix, not linux.
So I guess, I wouldn´t use vfork as default, but it might be possible to add a property, which will cause the library to use that. I.e. you write:
boost::process::child c("java.exe", "overhead.jar", boost::process::posix::use_vfork);
But I'd need to be able to check if vfork is available, so I can disable the property if not.
Would that be sufficient for your problem?
Naturally if the code still compiles on windows even though I'm using boost::process::posix::use_vfork(_if_possible) then yes for me all will be fine. But on the other hand from a library design point of view, shouldn't the library have the best smart default in terms of performance and overhead on a given platform ? Instead of having a flag telling : please do it the same but efficiently ? Because on linux vfork is nothing but obsoleted and for a scenario of using execve looks better to me.
On 17/06/2016 01:21, Gavin Lambert wrote:
Is this specifically for NOMMU linux?
MMU architectures shouldn't have this issue, as fork does a shared-memory-copy-on-write mapping so that the pages aren't actually duplicated unless written to, and the subsequent exec* unmaps the pages so this never happens (other than a bit of stack).
NOMMU architectures don't support those kinds of mappings, so have to be rewritten to use vfork instead (which is generally unsafe unless immediately followed by exec*, unless you know what you're doing).
Although the last time that I played with NOMMU, fork used to just fail; perhaps it's been changed to make copies of all the pages instead? If so, that would indeed be problematic for large parent processes.
Hi Gavin ;)
It's with an MMU but the parent process on this product is a memory-hungry-monster-jvm and the fork fails. I can be wrong, and it looks like you know more from what's happening there, but as long as I can remember the issue arose due to virtual memory commit, because fork on linux even though is optimized to not copy the whole process pages but to do copy-on-write, still needs to commit virtual memory, and overcommitment is not always allowed, or by default is heuristically allowed. Quoting man proc, the default is 0:
/proc/sys/vm/overcommit_memory This file contains the kernel virtual memory accounting mode. Values are:
0: heuristic overcommit (this is the default) 1: always overcommit, never check 2: always check, never overcommit
So it might fail, and it happens to fail often on a 80% RSS usage of the device RAM from the parent process which will do the fork. While vfork doesn't need to commit vm memory, or at least not so much as the parent process, but just what's needed for pid_t and a call to execve I find it a better alternative when someone does only do a fork followed by execve. But there might be considerations I don't understand, I never worked on the linux kernel process creation code, and so I'm just sharing from a dumb user point-of-view. Perhaps we could just remove the jvm, but as I proposed this to the java team they didn't invited me for the coffee anymore. :p