[Toybox] vfork() deprecated on macOS

enh enh at google.com
Mon May 16 08:47:49 PDT 2022


On Sat, May 14, 2022 at 5:59 AM Rob Landley <rob at landley.net> wrote:

> On 5/11/22 15:20, enh via Toybox wrote:
> > the toybox build is pretty noisy on a current mac, complaining that
> > vfork() should be replaced by fork() or posix_spawn().
>
> Sigh.
>
> > looks like it's because they've changed vfork() to just be fork() and
> > would like people to accept that they understand that by changing
> > their source to say fork() instead... (i'll copy & paste the man page
> > here because afaik apple doesn't give us anywhere to link to...)
>
> I.E. mac will never work on a nommu system. Got it.
>

eh, makes sense to me ... i recently rejected patches for non-4KiB page
sizes because there's no obvious path to shipping such a thing, so it's
just untested code that will bitrot immediately. (exhibit A: "this isn't
the first time someone's tried to clean up the hard-coded 4096es".)


> >      The vfork system call can be used to create new processes. As of
> macOS
> >      12.0, this system call behaves identically to the fork(2) system
> call,
> >      except without calling any handlers registered with
> pthread_atfork(2).
>
> That's very much not what it's for. Apple hasn't got anybody left there who
> understands why it was there in the first place.
>

for the systems macOS _does_ run on though, the "the fork() ... exec()
model doesn't work great if you have lots of fds/page table entries/etc"
problem is what they're more likely to be thinking about. linux added
close_range() as a workaround for the fd problem, whereas Apple is (afaik)
the only kernel that's actually implemented posix_spawn() as a system call.
so they can theoretically at least -- i've never poked deeper -- do a
better job than anyone else of avoiding unnecessary work when spawning.


> (There are more nommu processors in the world than there are mmu
> processors.
> It's sort of a "total weight of all insects" vs "total weight of all
> mammals"
> thing. You just don't _notice_ them...)
>

aye, but zero of them are running macOS :-)


> >      This system call is deprecated. In a future release, it may begin
> to return
> >      errors in all cases, or may be removed entirely.  It is extremely
> strongly
> >      recommended to replace all uses with fork(2) or, ideally,
> posix_spawn(3).
> >
> > weirdly it looks like you can use _POSIX_C_SOURCE to make this go
> > away? from their unistd.h:
> >
> > #if !defined(_POSIX_C_SOURCE)
> > __deprecated_msg("Use posix_spawn or fork")
> > #endif
> > pid_t    vfork(void) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
>
> We can move that header into portability.h if we need to? It's #included
> before
> the rest for a reason...
>
> > -Wno-deprecated-declarations in configure works too,
>
> I'm happy to wait for it to break and then fix it better then. :)
>

ack.


> > though their
> > threat to make vfork() always fail in a future release makes me
> > question whether that's such a good idea. (i haven't followed apple
> > closely enough to know whether there's any precedent for violent
> > breakage like that. i'm not sure why you wouldn't just remove the
> > symbol rather than replace it with an implementation that always
> > fails?)
>
> Ask Rich Felker with his insistence that fork() must always be there on
> nommu
> systems and return -EINVAL, and me patching it out with an #ifdef in my
> build
> script.
>
> Rob
>
> P.S. A few years ago I did a contract at a place that ported an old system
> from
> wince to Linux and ran an ~80-thread .net app under mono, and every time
> they
> forked from one of those threads it froze the whole app for 75 miliseconds
> while
> it copied all of its memory to the new process. (Because forking from a
> thread
> defeats copy on write, the kernel doesn't even TRY to track it and just
> copies
> everything, which involves locks.) Unfortunately something needed 4ms
> response
> time to avoid going "boing". The fix was to replace the fork() with a
> vfork()
> which only froze the ONE thread that called it (until it could do the rest
> of
> its setup and _exit() or exec() the new process). No big memory copy, thus
> no
> latency spike. On a system that had an MMU, and yet...
>

yeah, i thought i'd already said (but didn't spot it in my quoted bits when
replying) that i've seen the Android system health folks switching a few
fork()s to vfork()s lately. i have no immediate plans to make vfork() ==
fork(). people manage to screw up enough with just fork() (or they get
really "clever" and try to use clone() directly) that i don't think i'd
save myself much of a headache that way.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20220516/104e43b2/attachment-0001.htm>


More information about the Toybox mailing list