Skip to content

0.13.2 --- a thread created from C++ is the thread that is joined - #31

Merged
Sunrisepeak merged 1 commit into
mainfrom
a-thread-crosses-into-cxx
Sep 13, 2026
Merged

0.13.2 --- a thread created from C++ is the thread that is joined#31
Sunrisepeak merged 1 commit into
mainfrom
a-thread-crosses-into-cxx

Conversation

@Sunrisepeak

@Sunrisepeak Sunrisepeak commented Sep 13, 2026

Copy link
Copy Markdown
Member

Every std::thread on Windows ended in an access violation when it was joined.

musl declares pthread_t twice — a pointer for C, unsigned long for C++ — and
the two agree wherever a long holds a pointer. Windows is LLP64, so C++ code
above this library kept the lower half of the thread's address. libc++ stores
pthread_t in std::thread, and pthread_join read through the truncated value:

wine: Unhandled page fault on read access to 00000000FE9B8B60 at address 000000014003B2BA
  -> pthread_timedjoin_np, musl/src/thread/pthread_join.c:16
     rax=00000000fe9b8b28   (the thread pointer, upper half gone)

On windows-2022 the same programs exit with 0xC0000005. Found through
lsp-mcpp's unit tests, whose thread and process tests crashed only on Windows.

  • musl/include/alltypes.h.in and the five generated alltypes.h: C++
    pthread_t is unsigned _Addr. _Addr is what musl already uses for size_t
    and uintptr_t; it is long on x86_64, aarch64 and riscv64, so nothing
    changes there, and long long on x86_64-windows.
  • musl/PATCHES.md records it as the fifth patched line, the same kind as the
    other four: a machine word carried through a long.
  • examples/threads-cxx asserts the width with static_assert (it does not
    compile for x86_64-windows-gnu before this change) and creates and joins a
    thread; CI runs it on every row.

Measured locally: the example fails to compile for x86_64-windows-gnu before
the change; after it, the Windows build prints joined: 0, value 42, result is the argument under Wine. With openkal-llvm-runtime pointed at this tree, std::thread,
a condition variable across threads and an exception thrown and caught inside a
thread all work under Wine.

0.13.2. Correction after merge: openkal-llvm-runtime pins openkal-musl = "0.13.1"
exactly (a consumer asking for 0.13.2 beside it is refused as irreconcilable), so
consumers reach this fix through openkal-llvm-runtime 0.9.3
(mcpplibs/openkal-llvm-runtime#18).

musl's C++ pthread_t was unsigned long, thirty-two bits on LLP64 Windows, so a
C++ program kept half of the thread's address and pthread_join faulted through
it; every std::thread there ended in an access violation. The declaration now
uses _Addr, which is long on every other target. examples/threads-cxx asserts
the width at compile time and joins a thread on every CI row.
@Sunrisepeak
Sunrisepeak merged commit dc84bf5 into main Sep 13, 2026
6 checks passed
@Sunrisepeak
Sunrisepeak deleted the a-thread-crosses-into-cxx branch September 13, 2026 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant