Files
RedBear-OS/local/patches/relibc/P5-robust-mutex-enotrec-fix.patch.bak
T
vasilito 5851974b20 feat: build system transition to release fork + archive hardening
Release fork infrastructure:
- REDBEAR_RELEASE=0.1.1 with offline enforcement (fetch/distclean/unfetch blocked)
- 195 BLAKE3-verified source archives in standard format
- Atomic provisioning via provision-release.sh (staging + .complete sentry)
- 5-phase improvement plan: restore format auto-detection, source tree
  validation (validate-source-trees.py), archive-map.json, REPO_BINARY fallback

Archive normalization:
- Removed 87 duplicate/unversioned archives from shared pool
- Regenerated all archives in consistent format with source/ + recipe.toml
- BLAKE3SUMS and manifest.json generated from stable tarball set

Patch management:
- verify-patches.sh: pre-sync dry-run report (OK/REVERSED/CONFLICT)
- 121 upstream-absorbed patches moved to absorbed/ directories
- 43 active patches verified clean against rebased sources
- Stress test: base updated to upstream HEAD, relibc reset and patched

Compilation fixes:
- relibc: Vec imports in redox-rt (proc.rs, lib.rs, sys.rs)
- relibc: unsafe from_raw_parts in mod.rs (2024 edition)
- fetch.rs: rev comparison handles short/full hash prefixes
- kibi recipe: corrected rev mismatch

New scripts: restore-sources.sh, provision-release.sh, verify-sources-archived.sh,
check-upstream-releases.sh, validate-source-trees.py, verify-patches.sh,
repair-archive-format.sh, generate-manifest.py

Documentation: AGENTS.md, README.md, local/AGENTS.md updated for release fork model
2026-05-02 01:41:17 +01:00

88 lines
3.7 KiB
Plaintext

Fix ENOTRECOVERABLE returned for non-robust mutexes and register main
thread in OS_TID_TO_PTHREAD.
The robust mutex liveness check (mutex_owner_id_is_live) was returning
ENOTRECOVERABLE for non-robust mutexes when the owner appeared dead.
Per POSIX, the behaviour of a non-robust mutex whose owner has died is
undefined; returning an error crashes every Rust std::sync::Mutex user.
For lock_inner, fall through to spin/futex-wait instead. For try_lock,
return EBUSY instead.
Additionally, pthread::init() never registered the main thread in
OS_TID_TO_PTHREAD, so any mutex owned by the main thread would always
appear to have a dead owner, making the liveness check unreliable.
diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs
index 8243a48..c455a67 100644
--- a/src/pthread/mod.rs
+++ b/src/pthread/mod.rs
@@ -43,9 +43,13 @@ pub unsafe fn init() {
thread.stack_size = STACK_SIZE;
}
- unsafe { Tcb::current() }
- .expect_notls("no TCB present for main thread")
- .pthread = thread;
+ let tcb = unsafe { Tcb::current() }
+ .expect_notls("no TCB present for main thread");
+ tcb.pthread = thread;
+
+ OS_TID_TO_PTHREAD
+ .lock()
+ .insert(Sys::current_os_tid(), ForceSendSync(tcb as *const Tcb as *mut Tcb));
}
//static NEXT_INDEX: AtomicU32 = AtomicU32::new(FIRST_THREAD_IDX + 1);
diff --git a/src/sync/pthread_mutex.rs b/src/sync/pthread_mutex.rs
index af0c429..1b2b3ca 100644
--- a/src/sync/pthread_mutex.rs
+++ b/src/sync/pthread_mutex.rs
@@ -136,14 +136,17 @@ impl RlctMutex {
Err(thread) => {
let owner = thread & INDEX_MASK;
- if !crate::pthread::mutex_owner_id_is_live(owner) {
- if !self.robust {
- return Err(Errno(ENOTRECOVERABLE));
- }
-
+ if !crate::pthread::mutex_owner_id_is_live(owner) && self.robust {
let new_value = (thread & WAITING_BIT) | FUTEX_OWNER_DIED | this_thread;
match self.inner.compare_exchange(
thread,
@@ -152,6 +155,12 @@ impl RlctMutex {
Ok(_) => return self.finish_lock_acquire(true),
Err(_) => continue,
}
+ } else if !crate::pthread::mutex_owner_id_is_live(owner) {
+ // Non-robust mutex with apparently-dead owner: per POSIX the
+ // behaviour is undefined. We conservatively keep spinning /
+ // futex-waiting rather than returning ENOTRECOVERABLE, which
+ // would crash any Rust std::sync::Mutex user.
}
if spins_left > 0 {
@@ -241,14 +250,17 @@ impl RlctMutex {
if current & FUTEX_OWNER_DIED != 0 || (owner != 0 && !crate::pthread::mutex_owner_id_is_live(owner)) {
- if !self.robust {
- return Err(Errno(ENOTRECOVERABLE));
- }
-
+ if self.robust {
let new_value = (current & WAITING_BIT) | FUTEX_OWNER_DIED | this_thread;
match self.inner.compare_exchange(
current,
@@ -257,6 +269,11 @@ impl RlctMutex {
Ok(_) => return self.finish_lock_acquire(true),
Err(_) => continue,
}
+ } else {
+ // Non-robust mutex: owner appears dead but POSIX behaviour is
+ // undefined; report busy rather than ENOTRECOVERABLE.
+ return Err(Errno(EBUSY));
+ }
}
return Err(Errno(EBUSY));