-
Notifications
You must be signed in to change notification settings - Fork 0
Description
In a multi-process benchmark using fork(), it is critical to ensure the parent (client) process does not
attempt to connect or send messages before the child (server) process has completed its initialization.
To make our benchmark robust and reliable, we must implement a deterministic synchronization mechanism.
Proposed Solution
A standard and highly effective method for this is to use a pipe. The pipe() system call (available via the nix
crate) creates a pair of connected file descriptors, which can be used for one-way communication.
The synchronization flow should be as follows:
- Before Fork: The main process creates a pipe using
nix::unistd::pipe(). - After Fork:
- The parent process (client) closes the write end of the pipe.
- The child process (server) closes the read end of the pipe.
- Child Process Logic:
- The child proceeds to initialize the server-side transport (
transport.start_server()). - If initialization is successful, the child writes a single byte to its write end of the pipe and then
closes it. - If initialization fails, the child logs the error and exits immediately without writing to the pipe.
- The child proceeds to initialize the server-side transport (
- Parent Process Logic:
- The parent process immediately attempts a blocking
read()on its read end of the pipe. - If the
read()call returns successfully (with one byte), the parent knows the child is ready and can
proceed with its client-side logic (transport.start_client()). - If the
read()call returns 0 (EOF), it means the child closed its end of the pipe without writing. The
parent should interpret this as a failure,wait()for the child to collect its exit status, and terminate
the benchmark for that mechanism.
- The parent process immediately attempts a blocking
Acceptance Criteria
- A pipe is created before the
fork()call in theBenchmarkRunner. - The parent process blocks on
read()from the pipe before it attempts to initialize its client transport. - The child process writes a byte to the pipe only after its server transport has been successfully
initialized. - If the child process fails to initialize, the parent process correctly detects the failure via the pipe
and aborts the test for that mechanism. - The synchronization mechanism is implemented for all IPC mechanisms running under the multi-process model.
- The old
usleep()or any other non-deterministic delay for synchronization is removed.
Context
This is a high-priority task (P2) for ensuring the reliability and correctness of the benchmark suite.
This task is dependent on the completion of the multi-process refactoring (Issue #74). The
synchronization logic will be built into the new fork()-based execution flow.