mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
[GH-ISSUE #68] fork: a child forked from a cthreads process intermittently dies with SIGSEGV (stress-thread fork) #63
Labels
No labels
bug
documentation
enhancement
enhancement
good first issue
help wanted
help wanted
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
github-starred/RhapsodiOS#63
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @raynorpat on GitHub (Oct 19, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/68
Symptom
stress-thread forkfailed once with a child process killed by SIGSEGV:This was in the phase 4
--fsacceptance UFS run (2026-10-19, #60 kernel, ffs-perf8235b390f), with every category running. Status 0xb is SIGSEGV.What the test does
A worker starts several cthreads that loop locking a shared
mutex_tand updating counters. The main threadfork()s while they run. The child doesmalloc(1 MB), fills and checks it, and calls_exit(0)(src/Commands/stress/thread/thread.c).The child crashing, rather than hanging, rules out the lock-held-at-fork case that #49's analysis covered.
fork.salready runs_cthread_fork_prepare/_cthread_fork_childand the dyld fork hooks.Reproduce
Intermittent:
./thread/stress-thread -s 4 -n 4 fork, many iterations;run 1with all categories under load.Evidence:
vm/work/ffsbench/runs/p4-accept/stress-0/thread.out. The test's core dump, if one was written, goes to/coreson the guest (the snapshot is gone, so rerun with cores enabled to get one).Where to look
Related: #42 (fork exhaustion panic), #49 (fork "hang", a test bug). Found by the stress suite.
@raynorpat commented on GitHub (Oct 20, 2026):
Fixed in Libc by
61ca43ca5on ffs-perf (cherry-picked from issue-68 428749746).It isn't #71. On a kernel with the FSAVE workaround (
4fd6d07b6),stress-thread forkalone was clean: about 8,400 forks over 1 hour. Underrun -aload the same failure came back (child-status status=0x8b) 3 times in about 140 rounds.What the cores show. All 3 cores are the same:
_cthread_fork_child+0xa6 while it walks the cthread run queue, whose head is 0x80000000.cthread_body→condition_signal(&t->done)for a cthreadt.t, freed it, allocated it again and queued it.ttwice: once in_cproc_fork_child(free(p->incarnation), cprocs.c ~646) through the stale incarnation, and again from the run queue.Root cause. In
cthread_body(threads.subproj/cthreads.c~204-212), the cproc sets T_RETURNED and dropst->lockbefore it signalst->doneand before it clears its incarnation withcthread_assoc(self, NO_CTHREAD). The joiner can freetwhile the cproc still points at it.Fix. The cproc clears its incarnation and signals the joiner while it still holds
t->lock.Verification. The test guests run DR2's System binary, not one built from
src/Libc-1, so:cthread_body, on snapshot guests only (vm/work/issue-68/patchsys.py);run -a(about 20,000 forks), 0 fork failures, 0 cores;check-threadpasses.A HEAD libsystem couldn't be built for the image (getsid/mlock/munlock syscalls, librpcsvc-obj missing), so the shipped binary itself hasn't been run.
The other failures under load (SIGSEGV in fdpass and stress-misc workers) were the fifo vnode reuse fixed by #67. Its kernel-fault-to-SIGSEGV path is #73.