-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprocess-model.plan
More file actions
100 lines (90 loc) · 4.88 KB
/
process-model.plan
File metadata and controls
100 lines (90 loc) · 4.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# Process model migration plan (v1)
Goal:
- Make shell/tools usable with real process semantics for fork/exec/wait without
pretending to be a cooperative rollback model.
- Preserve most existing runtime infrastructure and syscall dispatching.
- Move control-plane process lifecycle to host-side orchestration with a real process
table and explicit wakeup semantics.
## Phase 0 — Contracts + Verification gates (this file is the source of truth)
### Behavioral contracts
- Process identity:
- `getpid()` returns the currently running process pid.
- `getppid()` returns parent pid (0 for top-level process).
- `gettid()` is still thread-local (existing `g_sched` path remains for true threads).
- `getpgid`/session/pgid behavior is explicit and deterministic; default pgid = pid.
- Lifecycle:
- `fork/clone` process path:
- parent returns child pid on success
- child returns 0 and continues independently from cloned context
- no rollback of parent state is part of this API contract.
- `execve` executes in-place for current process context and may replace the
executable image.
- `exit/exit_group` terminates current process only.
- `wait4` returns a child’s exit status; blocks (or yields) until exit unless
WNOHANG is requested.
- child state transitions: Running → Exited → Reaped.
- FD/stdio contract:
- descriptors inherit from parent copy rules.
- redirections (`dup2`, pipe endpoints, close-on-exec style behavior) are tracked
per child context and restored/closed through host mediation.
- Error contract:
- unsupported semantics return Linux errno explicitly; no silent fake success.
- no parent state rollback is treated as success if not actually performed.
### Verification gates (must pass before phase progression)
1. `getpid`/`getppid` contract: parent and child can observe distinct pids after fork.
2. `fork`: parent gets child pid, child gets 0 and reaches next instruction.
3. `wait4`: parent receives exit status and blocked parent resumes exactly once.
4. `execve` in child does not mutate a separate parent context.
5. Shell smoke smoke:
- prompt appears after child exit
- simple job pipeline works (`printf hi | cat`)
- fd redirects (`/bin/sh -c 'echo x > /tmp/a'`) behave as expected.
6. No regressions in current non-fork syscalls.
## Phase 1 — In-runtime process model + host-aware process table
### Required implementation
- Keep syscall table dispatch unchanged.
- Add a first-class process model in runtime layer:
- fixed-size process table
- `pid`, `ppid`, `pgid`, state, exit status
- current running process pointer
- helper APIs for:
- allocate pid
- register process
- mark exit/reap
- resolve current process identity
- Replace hardcoded identity syscalls:
- `getpid`/`getppid` stop returning constant `1/0`.
- Thread-only pids remain on `g_sched` where applicable.
- Keep `g_fork` as bootstrap compatibility bridge for now:
- remove rollback-based assumptions from identity path.
- decouple pid identity from rollback behavior.
- Add host-oriented process metadata events (no worker-per-process yet):
- `on_process_spawn`, `on_process_exit`, `on_process_waiter_wakeup`.
- host stores lifecycle; runtime consumes ids for syscalls only.
- Concrete phase-1 wiring to implement in repo now:
- emit `ProcessEvent` records from runtime on spawn/exit/wait.
- expose `friscy_drain_process_events` JS export for host consumption.
- add worker passthrough message `process-events` and a host-side buffer (`window.__friscyProcessEvents`).
- verification hooks to run before phase-2:
- `friscy_getppid` always resolves from process table for child and parent.
- `wait4(WNOHANG)` returns `0` while child is Running.
- `wait4` emits `WaitWakeup` and reaps process entry once child exits.
### Pass criteria for entering Phase 2
- all Phase 0 gates pass on at least `/bin/sh`, `busybox`, and `node` basic scripts.
- no user-visible rollback behavior (parent-state rewind) in `getpid`/`getppid`.
## Phase 2 — Host scheduler + wait/wakeup semantics
- Parent continues immediately after fork.
- Parent wait semantics become explicit wait queues and wakeups.
- Replace fake "already exited" assumption in `wait4`.
## Phase 3 — Performance and isolation
- Snapshot strategy:
- fast copy-on-write-like memory ownership model (or page-window copy for hot path)
- lazy copy of exec-only/code regions and mutable region cloning on write.
- Optional worker-per-process promotion:
- start with one worker + process slots
- promote to dedicated worker per process only where contention/perf merits.
## Open questions for implementation
- Is `g_sched` limited to `CLONE_THREAD` only or should any clone-style thread mode
be converted fully to process table + scheduler model?
- What minimal process events are required for shell/job-control parity at phase 2?
- Which fork-heavy workloads must be first-class in v1 (shell, git, node, python)?