[go: up one dir, main page]

|
|
Log in / Subscribe / Register

Toward race-free process signaling

Toward race-free process signaling

Posted Dec 6, 2018 20:07 UTC (Thu) by rweikusat2 (subscriber, #117920)
In reply to: Toward race-free process signaling by jspenguin
Parent article: Toward race-free process signaling

There's a race here nevertheless: The pid of a process one wants to send a signal to can only be known at some time x + n, x being the time when fork returned and n the delay until the pid was communicated to the process desiring to use it. There's no way this process can determine if the pid is still used by the other process it wanted to send a signal to by the time it tries to use it, be it roundabout via proc or directly via kill.


to post comments

Toward race-free process signaling

Posted Dec 6, 2018 20:11 UTC (Thu) by nopsled (guest, #129072) [Link] (7 responses)

I think there are plans to introduce a new variant of clone that has CLONE_NEW or so as an additional flag that returns a process descriptor (since clone has already run out of flags).

Toward race-free process signaling

Posted Dec 6, 2018 20:28 UTC (Thu) by quotemstr (subscriber, #45331) [Link] (6 responses)

The next clone, instead of just having a bigger flag parameter, really should, instead, look something like this:

#define CLONE2_SHARE_VM (1<<0) /* VALUE is a bool: default to true */
#define CLONE2_OUTPUT_FD /* VALUE is an int*: on success, clone2 writes a procfd FD */
...

struct clone2_parameter {
void* value; /* In, in-out, or out depending on NAME */
int name; /* CLONE2_XXX; after the pointer for 32-bit ABI compat crap */
};

/* Make a new task (process or thread). The new process's properties are mumble.
clone2_parameters override these defaults. If multiple clone2 parameter structures
have the same NAME, the last one wins. Return child PID on success; on failure, -1 with errno set. */
int clone2(const struct clone2_parameter* parameters, int nparameters);

This way, we can create an interface as rich as we want, in an extensible way, without ever again having to make a new god damn process creation system call. It'd also let us implement a posix_spawn directly, without vfork.

Toward race-free process signaling

Posted Dec 8, 2018 5:51 UTC (Sat) by dw (subscriber, #12017) [Link] (5 responses)

I've been working on a deep dive into the history of process management on UNIX, and noticed all these kernel implementations of posix_spawn() popping up (NetBSD, OS X, Solaris). While their rationale is solid (avoiding huge pointless serializing VM copies), directly implementing posix_spawn() looks like a potential mistake, due to the perpetual incompleteness of that interface.

This led to thoughts about a compromise, and a potentially reasonable answer: something like a combined fork+exec, where the VM is not preserved and inherited FDs are explicitly specified. The target of the exec is a helper binary to implement the desired post-fork behavior. Configuration of the helper would be done e.g. over a pipe or a memfd.

If a new clone() variant is under discussion as described here, another option might be to address the VM problem by allowing the variant to specify memory regions preserved in the child. posix_spawn() only requires access to existing file descriptors and say, one page describing the new child configuration.

The point of both options is to keep that huge inflexible interface in userspace, and some system call that still provides all the performance benefit, for applications where posix_spawn() doesn't go far enough (e.g. changing security credentials or similar)

Toward race-free process signaling

Posted Dec 8, 2018 5:55 UTC (Sat) by dw (subscriber, #12017) [Link]

Forgot to mention, the biggest motivation for a userspace spawn may be the sheer size of an equivalent kernel implementation ;) https://github.com/SilkieDragon/xnu/blob/0a798f6738bc1db0...

Toward race-free process signaling

Posted Dec 8, 2018 6:00 UTC (Sat) by Cyberax (✭ supporter ✭, #52523) [Link] (3 responses)

I thought that one of the better ideas is to make all the relevant process-management functionality to accept an explicit process file descriptors. And then the final piece - ability to create a process in a "suspended" state.

Intermediary executables are just a crutch.

Toward race-free process signaling

Posted Dec 8, 2018 6:15 UTC (Sat) by dw (subscriber, #12017) [Link] (2 responses)

The trouble is that there is an almost unlimited set of fork() use cases that can't be addressed by posix_spawn(), and no sensible finite set of APIs can ever fully describe what was already possible post-fork. As a contrived example, creating a connected UNIX client socket attached to the new process stdio, where peercred accurately reflects the connecting process is the new process.

Toward race-free process signaling

Posted Dec 8, 2018 9:03 UTC (Sat) by Cyberax (✭ supporter ✭, #52523) [Link] (1 responses)

> As a contrived example, creating a connected UNIX client socket attached to the new process stdio, where peercred accurately reflects the connecting process is the new process.
You still will be able to dup() sockets into the new process. I'm not sure how you would forge the peercred, though.

Toward race-free process signaling

Posted Dec 8, 2018 15:38 UTC (Sat) by dw (subscriber, #12017) [Link]

The question is not whether one contrived example has an incomplete solution in the proposed scheme, but whether even a reasonable subset of use cases could be catered for even when approaching something like 100% churn in the interface, implementation, locking requirements and security model for almost all existing system calls, without forcing users to resort to e.g. vfork or debugging APIs (which they may lack privilege to use) to fill the remaining gaps.

We don't need to answer it for ourselves, Windows had process handles since prehistory, where you find endless hacks like this to cope with their process creation API remaining incomplete after almost 30 years.

Toward race-free process signaling

Posted Dec 6, 2018 20:13 UTC (Thu) by quotemstr (subscriber, #45331) [Link] (3 responses)

And that's why we'll eventually need a variant of clone(2) that returns a file descriptor. That's out of scope for the present patch, though.

Toward race-free process signaling

Posted Dec 6, 2018 20:47 UTC (Thu) by josh (subscriber, #17465) [Link] (2 responses)

I wrote CLONE_FD a while ago; if anyone wants to pick it up and run with it, the only open remaining from the discussion at the time was that people wanted a more detailed ptrace test suite to make sure nothing in the intricate interaction between ptrace, reparenting, and child processes broke.

Toward race-free process signaling

Posted Dec 9, 2018 1:01 UTC (Sun) by brauner (subscriber, #109349) [Link] (1 responses)

Fwiw, if this patch lands I intend to pick yours up and would very much like your input.

Toward race-free process signaling

Posted Dec 9, 2018 12:50 UTC (Sun) by josh (subscriber, #17465) [Link]

Great! Happy to help.

Toward race-free process signaling

Posted Dec 6, 2018 20:15 UTC (Thu) by jspenguin (guest, #120333) [Link] (8 responses)

But with fork, there's no race condition, because the process doing the signaling is the direct parent. Even if the forked child exits immediately, before fork even returns in the parent, the process will remain in the table as a zombie. As long as the parent process signals the child before calling wait, it is impossible for that pid to refer to any other process. Signaling a zombie has no effect, even SIGKILL.

Toward race-free process signaling

Posted Dec 6, 2018 20:42 UTC (Thu) by quotemstr (subscriber, #45331) [Link] (6 responses)

There's still a race, even with direct children, when multiple components in a process don't coordinate with each other and each want to run child processes for their own purpose. For example, the Java VM basically has a constant waitpid(-1) running; if some shared library in that process makes a subprocess, and that subprocess dies, then Java's waitpid might reap it before the shared library does, making the shared library's process manipulation malfunction in various exciting ways.

One of my long-term goals is to make it possible for unrelated components that happen to share a process to easily manage their own sets of children.

Toward race-free process signaling

Posted Dec 6, 2018 21:01 UTC (Thu) by rweikusat2 (subscriber, #117920) [Link] (4 responses)

In principle, this can be solved with an intermediate process acting as relay for "a component" desiring to run controlled processes in face of a 'hostile' VM interfering with that: It would create and destroy more processes on behalf on "the component" and would escape the VM-autoreaper by not terminating.

Toward race-free process signaling

Posted Dec 7, 2018 20:55 UTC (Fri) by rweikusat2 (subscriber, #117920) [Link] (3 responses)

OTOH, this ("unrelated components sharing a process") is pretty much a travesty: As these components share an address space, they are related, regardless if they want this or not, and have to cooperate with each other. If they're really unrelated, they ought to run in different processes.

There's little point in coding against basic system design choices like this one (just because other systems are or were based on different design choices).

Toward race-free process signaling

Posted Dec 8, 2018 21:46 UTC (Sat) by quotemstr (subscriber, #45331) [Link] (2 responses)

It's perfectly reasonable for a process to host components that are developed separately and that aren't aware of each other. That ship sailed a long time ago.

Toward race-free process signaling

Posted Dec 8, 2018 22:42 UTC (Sat) by smurf (subscriber, #17840) [Link]

Today, the best way to wait on N child processes in that kind of environment is to spawn N threads, each of which calls waitpid(). At least with a clone2-returning-a-process-FD you can reduce that to a single, race-free poll().

Toward race-free process signaling

Posted Dec 9, 2018 13:20 UTC (Sun) by rweikusat2 (subscriber, #117920) [Link]

"It's commonly done" is not the same as "it's perfectly reasonable". That's what I already wrote: The "hosted components" are not separate and have to be aware of each other if they're running in a shared address space/ single process. In the given context, a process can manage its children which includes reliably signalling them but multiple "components" sharing a process can't separate "their children" from each other. If this has to be done, a number of (possibly cooperating) processes have to be used. A process is the fundamental system abstraction for separating independently executing entities from each other. Hence, if such separation is desired, it's sensible to use processes for that.

One could argue backwards and forwards here whether or not this design choice is or was sensible but "that ship sailed a long time ago" and it's better to put the available facilities to (some) good use than to keep fighting them. Instead of bemoaning fork (an undercurrent in this conversation), one can try to find uses for it (and there are plenty -- I use fork much more often than exec).

Eg, some program I have been writing in the past (idea more recently reused in a different context) had to do "HTTP requests" to interact with some set of servers. In the 'modern' internet, where TCP connections can suddenly turn into black holes for all kinds of weird reasons (aka random "session timeouts" enforced by firewalls), this obviously needs some sort of timeout. An extremely simple way to implement this reliably is to fork a process tasked with doing the HTTP interaction synchronously (easily possible because the forked process runs a copy of the forking program) and let the parent enforce the timeout. Or use alarm to arrange for a SIGALRM to be delived to the forked process after some time. The parent can then just wait until the child terminated, determine its fate via exit status and possibly retry the request.

Toward race-free process signaling

Posted Dec 7, 2018 14:27 UTC (Fri) by kjp (guest, #39639) [Link]

> One of my long-term goals is to make it possible for unrelated components that happen to share a process to easily manage their own sets of children.

Something like the windows Job API? https://docs.microsoft.com/en-us/windows/desktop/procthre...

Toward race-free process signaling

Posted Dec 6, 2018 20:45 UTC (Thu) by rweikusat2 (subscriber, #117920) [Link]

That's obviously correct but there's no need for a new mechanism to send signals in this case, either. The parent can just use kill.


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds