Rethink how we give file descriptors / handles to child processes
Categories
(Core :: IPC, enhancement, P3)
Tracking
()
People
(Reporter: jld, Assigned: nika)
References
Details
(Whiteboard: [overhead:noted])
Attachments
(14 files)
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review |
Comment 1•7 years ago
|
||
Updated•7 years ago
|
Comment 2•7 years ago
|
||
Reporter | ||
Comment 3•7 years ago
|
||
Reporter | ||
Comment 4•7 years ago
|
||
Updated•7 years ago
|
Reporter | ||
Comment 5•4 years ago
|
||
Here's an idea: assuming a centralized list of all possible handles needed at startup, then on both Windows and Unix we could just pass one command-line flag, -fdMap
or something, with a comma-separated list of the fd/handle values in decimal, in the order that they're listed in the big enum.
Both platforms have in-band nulls (-1
on Unix, 0
a.k.a. NULL
on Windows) usable to represent handles that aren't passed; any that aren't meaningful on the platform / build type in question (e.g., IPC on Windows) could even be handled this way instead of trying to ifdef them. UniqueFileHandle
should be useful here; both GeckoChildProcessHost
and whatever global singleton is created in the child process can have an array of them, behind a suitable abstraction.
For Unix, the fds could be 3+n
as currently, or use the same values as the parent (just clearing close-on-exec instead of using dup2
, similar to Windows handle inheritance), or even be randomized; it won't really matter, although a nondeterministic option would detect accidental hard-coding.
Some of these are for shared memory, so we'll also want to allow adding a length (maybe with syntax like <fd-or-handle>:<length>
) and converting to/from base::SharedMemory
; this is already being done with the existing collection of ad-hoc solutions.
Android is its own thing, but fundamentally we just need to get an array of optional fds (and optional lengths) to/from Java, message it to the child as we're currently doing with the existing collection of fds, and then it can proceed like normal Unix.
Updated•2 years ago
|
Assignee | ||
Comment 6•5 months ago
|
||
I have some WIP patches which rework how we do child process handle passing, so claiming the bug.
Assignee | ||
Comment 7•5 months ago
|
||
It is never used outside of the parent process.
Assignee | ||
Comment 8•5 months ago
|
||
This is convenient in cross-platform code which needs to work with
UniqueFileHandle
objects. dup
is not supported by wasi, so the method isn't
available there.
Depends on D221369
Assignee | ||
Comment 9•5 months ago
|
||
This patch implements the majority of the public interface for the new IPC
handle passing design.
The rough design is an expansion of geckoargs
to allow passing
UniqueFileHandle
arguments to child processes. This replaces the existing
extra options array to make the list of files explicit.
This currently just replaces things which were already passed this way on the
command line from outside of GeckoChildProcessHost. Note that this does not
migrate callers which were not already passing file handles using geckoargs,
and does not implement the actual OS-level support for passing arguments this
way.
Depends on D221370
Assignee | ||
Comment 10•5 months ago
|
||
This helps unify some logic between platforms, and removes some positional
arguments from the command line, so it ended up in this patch stack, despite
not technically being required to pass FDs directly.
Depends on D221371
Assignee | ||
Comment 11•5 months ago
|
||
The crash reporter pipe was previously passed as a positional argument with
custom code for each platform. On some platforms it is implemented as a file
being passed, which is now directly supported by geckoargs.
Depends on D221372
Assignee | ||
Comment 12•5 months ago
|
||
The initial IPC pipe was previously the only argument passed as a chromium
command line flag. This changes it to instead be passed using geckoargs,
unifying the platforms, and removing the need for specific handling on every
platform.
Depends on D221373
Assignee | ||
Comment 13•5 months ago
|
||
The other file descriptors which used to use FDs 3 and 4 are no longer going to
be passed with fixed FDs, and will instead be passed using the new geckoargs
system. Due to the low-level and linux-specificity of the linux-sandbox,
migrating it to use geckoargs is a bit more difficult, so it is being left
using manual FD inheritance/remapping.
The environment variable for chroot has also been changed in this patch to
contain the FD to use to communicate with the chroot server. In a future patch,
the chroot server will be unable to use a fixed FD when the process has been
forked from the fork server, and this provides a mechanism for changing this
behaviour.
Depends on D221374
Assignee | ||
Comment 14•5 months ago
|
||
Windows is the simplest platform to support, as HANDLEs are inherited by
identity into the child process, and there's less variance between different
OSes.
This effectively re-implements the existing behaviour used for HANDLE
passing on Windows by passing the handle directly on the command line.
Depends on D221375
Assignee | ||
Comment 15•5 months ago
|
||
This effectively mimics the old system using fixed FDs for passing the
arguments down.
An in-memory array of FDs is used to track which FD corresponds with
with file argument, which is initialized to the fixed offsets, in order
to allow platforms which cannot use fixed FDs in their child processes
to specify explicit files being passed down. This will be used in the
fork server, for Android, and for iOS.
Depends on D221376
Assignee | ||
Comment 16•5 months ago
|
||
This changes how file descriptors are passed to Android child processes to
support the new ChildProcessArgs model. Instead of explicit lists of FDs to pass
around, a single array of FDs is passed from the parent process into the child
service and then passed into GeckoArgs.
Depends on D221377
Assignee | ||
Comment 17•5 months ago
|
||
The code which decodes the XPC bootstrap message hasn't landed into
mozilla-central yet, so only the serializing side in GeckoChildProcessHost is
updated here.
Depends on D221378
Assignee | ||
Comment 18•5 months ago
|
||
After this change, the fork server no longer uses a Dup2Sequence to set
fixed FD offsets when starting child processes, instead using the new
geckoargs system.
Because this was pretty disruptive to thow the fork server works and was
previously integrated into LaunchApp, the forkserver code has generally been
moved out of the chromium codebase, and inlined into the ForkServer files.
As noted in a previous part, the linux sandbox code does not use
geckoargs, as it is low-level. For the kSandboxReporterFileDesc
we can
cheat, because every process wants the same FD created once in the
parent process at the same FD offset. As this will also have been passed
to the fork server process when it was created, we can just allow new
child processes forked from the fork server to inherit this FD from the
fork server.
In contrast, the chroot sandbox pipe is actually created within the
forkserver while forking. To handle this, the environment variable used
to signal that the chroot server should be used is used to specify the
FD where the pipe can be found, and is not set to a fixed value in the
fork server.
Finally, the primary IPC pipe used by the fork server is also changed to
be passed using geckoargs into the fork server, and the fork server
being used is made more explicit in GeckoChildProcessHost, as launching
using the fork server now requires different arguments than launching
normally (due to needing to pass down the ChildProcessArgs).
Depends on D221379
Updated•5 months ago
|
Comment 19•5 months ago
|
||
Assignee | ||
Comment 20•5 months ago
|
||
Comment 21•5 months ago
•
|
||
Backed out for causing multiple failures
- Backout link
- Push with failures
- Failure Log
- Failure line: TEST-UNEXPECTED-ERROR | /builds/worker/checkouts/gecko/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java:110:13 | Variable 'fds' should be declared final. (com.puppycrawl.tools.checkstyle.checks.coding.FinalLocalVariableCheck)
- Failure Log2
- Failure line2: error: test failed, to rerun pass
-p style --lib
error: 1 target failed:
gmake[4]: *** [/builds/worker/checkouts/gecko/config/makefiles/rust.mk:548: force-cargo-test-run] Error 101
Comment 22•5 months ago
|
||
Something like this would fix the rusttest issue. The mach port stuff does the same:
diff --git a/mfbt/UniquePtrExtensions.h b/mfbt/UniquePtrExtensions.h
index c93f76a008711..c5e45f92f7561 100644
--- a/mfbt/UniquePtrExtensions.h
+++ b/mfbt/UniquePtrExtensions.h
@@ -103,6 +103,7 @@ typedef int FileHandleType;
# error "Unsupported OS?"
#endif
+#if !defined(RUST_BINDGEN)
struct FileHandleHelper {
MOZ_IMPLICIT FileHandleHelper(FileHandleType aHandle) : mHandle(aHandle) {
#if defined(XP_UNIX) && (defined(DEBUG) || defined(FUZZING))
@@ -162,6 +163,7 @@ struct FileHandleDeleter {
using receiver = FileHandleType;
MFBT_API void operator()(FileHandleHelper aHelper);
};
+#endif
#if defined(XP_DARWIN) && !defined(RUST_BINDGEN)
struct MachPortHelper {
@@ -215,6 +217,7 @@ struct MachPortSetDeleter {
template <typename T>
using UniqueFreePtr = UniquePtr<T, detail::FreePolicy<T>>;
+#if !defined(RUST_BINDGEN)
// A RAII class for the OS construct used for open files and similar
// objects: a file descriptor on Unix or a handle on Windows.
using UniqueFileHandle =
@@ -227,6 +230,7 @@ inline UniqueFileHandle DuplicateFileHandle(const UniqueFileHandle& aFile) {
return DuplicateFileHandle(aFile.get());
}
#endif
+#endif
#if defined(XP_DARWIN) && !defined(RUST_BINDGEN)
// A RAII class for a Mach port that names a send right.
It's a bit unfortunate but needed due to how we override UniquePtr to be otherwise usable from rust...
Assignee | ||
Comment 23•5 months ago
|
||
Apparently rust bindgen uses a hack which assumes all specializations of
UniquePtr
have the basic layout and use a pointer member with an empty
deleter.
This incorrect assumption unfortunately comes up for UniqueFileHandle,
which replaces the pointer type using the deleter with a file handle
helper type.
As this fails to build with RUST_BINDGEN, this patch takes the same
approach as bug 1802320, and just disables building these types when
building headers for bindgen.
This does not fix the general issue of bindgen making incorrect
assumptions about the layout of UniquePtr with non-default deleters.
Ideally, all non-default deleters should be made opaque.
Assignee | ||
Comment 24•5 months ago
|
||
I believe the 2 follow-up parts I have added will fix these failures.
Comment 25•4 months ago
|
||
Comment 26•4 months ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/409db639b50d
https://hg.mozilla.org/mozilla-central/rev/7aa8871e9e3e
https://hg.mozilla.org/mozilla-central/rev/25a973b1e0f5
https://hg.mozilla.org/mozilla-central/rev/aa5a1a50b422
https://hg.mozilla.org/mozilla-central/rev/bdc0a11f0ca9
https://hg.mozilla.org/mozilla-central/rev/7664f0f62585
https://hg.mozilla.org/mozilla-central/rev/7a0410a922e3
https://hg.mozilla.org/mozilla-central/rev/33fb31912242
https://hg.mozilla.org/mozilla-central/rev/e1bf17be60c4
https://hg.mozilla.org/mozilla-central/rev/74c3288e212b
https://hg.mozilla.org/mozilla-central/rev/a14291928dd2
https://hg.mozilla.org/mozilla-central/rev/2049ff50c110
https://hg.mozilla.org/mozilla-central/rev/fea31ce1c38c
https://hg.mozilla.org/mozilla-central/rev/79d3abe7bd3c
https://hg.mozilla.org/mozilla-central/rev/a2e2c7a7fc7c
Updated•3 months ago
|
Description
•