Skip to content

Commit dc84bf5

Browse files
authored
0.13.2 --- a thread created from C++ is the thread that is joined (#31)
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.
1 parent e51e0b1 commit dc84bf5

12 files changed

Lines changed: 99 additions & 9 deletions

File tree

.github/workflows/ci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,19 @@ jobs:
593593
# compile. It is run as well as built so that something links afterwards,
594594
# which is what distinguishes a source that compiles from a package that
595595
# works.
596+
# ⭐ A THREAD CREATED FROM C++ IS THE THREAD THAT IS JOINED.
597+
#
598+
# musl's C++ `pthread_t` was `unsigned long`, which is thirty-two bits on
599+
# Windows, so every std::thread there faulted when joined. The probe's
600+
# static_assert is the criterion and the run shows the value surviving a
601+
# started context. musl/PATCHES.md, `include/alltypes.h.in`.
602+
- name: A thread created from C++ is the thread that is joined
603+
env:
604+
MCPP_TARGET: ${{ matrix.target }}
605+
run: |
606+
bash tools/run-probe.sh examples/threads-cxx threads-cxx
607+
grep -q 'value 42, result is the argument' examples/threads-cxx/run.log
608+
596609
- name: A program may use the names the internal overlay defines
597610
env:
598611
MCPP_TARGET: ${{ matrix.target }}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ musl reaches its kernel through seven inline functions declared once per
7474
architecture. Replacing that one header is the whole of the redirection; the
7575
1345 sources that make up the library are compiled unmodified.
7676

77-
`musl/PATCHES.md` lists the whole of what is not unmodified: **four patched
77+
`musl/PATCHES.md` lists the whole of what is not unmodified: **five patched
7878
lines**, all of one kind — a machine word carried through a variable declared
7979
`long`, which is not a machine word on one of the three targets — and **eleven
8080
replaced sources**. Five of the eleven are replaced for the same reason: each

examples/threads-cxx/mcpp.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "threads-cxx"
3+
version = "0.1.0"
4+
5+
[dependencies]
6+
openkal-musl = { path = "../.." }
7+
8+
[targets.threads-cxx]
9+
kind = "bin"
10+
main = "src/main.cpp"
11+
12+
[build]
13+
cxx_runtime = "host-coupled"

examples/threads-cxx/src/main.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* A thread created from C++ is the thread that is joined.
2+
*
3+
* musl declares `pthread_t' twice: a pointer for C, and `unsigned long' for C++.
4+
* The two agree wherever a long holds a pointer, which is every architecture
5+
* musl was written for. Windows is LLP64 --- a long is thirty-two bits --- so a
6+
* C++ program kept the lower half of the thread's address, and pthread_join read
7+
* through the truncated value. libc++'s std::thread stores exactly this type,
8+
* so every std::thread on that system ended in an access violation when joined.
9+
*
10+
* ⭐ THE static_assert IS THE CRITERION, and it is a compile-time one: before the
11+
* change this file does not compile for x86_64-windows-gnu. The run afterwards
12+
* shows that the value survives the round trip through a started context.
13+
*/
14+
#include <pthread.h>
15+
#include <stdio.h>
16+
17+
static_assert(sizeof(pthread_t) >= sizeof(void*), "pthread_t must hold the address musl stores in it");
18+
19+
static void* work(void* arg)
20+
{
21+
*static_cast<int*>(arg) = 42;
22+
return arg;
23+
}
24+
25+
int main()
26+
{
27+
int failures = 0;
28+
int value = 0;
29+
pthread_t thread;
30+
if (pthread_create(&thread, nullptr, work, &value) != 0) {
31+
puts("pthread_create failed");
32+
return 1;
33+
}
34+
void* result = nullptr;
35+
const int joined = pthread_join(thread, &result);
36+
printf("joined: %d, value %d, result %s\n", joined, value, result == &value ? "is the argument" : "is not the argument");
37+
if (joined != 0) ++failures;
38+
if (value != 42) ++failures;
39+
if (result != &value) ++failures;
40+
printf("-- failures: %d --\n", failures);
41+
return failures == 0 ? 0 : 1;
42+
}

mcpp.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
namespace = "mcpplibs"
33
name = "openkal-musl"
4-
version = "0.13.1"
4+
version = "0.13.2"
55
description = "musl 1.2.5 redirected onto openkal: one C library, ported once, above every implementation of the specification rather than above one kernel."
66
license = "Apache-2.0"
77

musl-generated/aarch64-macos/bits/alltypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ typedef unsigned useconds_t;
272272

273273
#ifdef __cplusplus
274274
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
275-
typedef unsigned long pthread_t;
275+
typedef unsigned _Addr pthread_t;
276276
#define __DEFINED_pthread_t
277277
#endif
278278

musl-generated/aarch64/bits/alltypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ typedef unsigned useconds_t;
272272

273273
#ifdef __cplusplus
274274
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
275-
typedef unsigned long pthread_t;
275+
typedef unsigned _Addr pthread_t;
276276
#define __DEFINED_pthread_t
277277
#endif
278278

musl-generated/riscv64/bits/alltypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ typedef unsigned useconds_t;
262262

263263
#ifdef __cplusplus
264264
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
265-
typedef unsigned long pthread_t;
265+
typedef unsigned _Addr pthread_t;
266266
#define __DEFINED_pthread_t
267267
#endif
268268

musl-generated/x86_64-windows/bits/alltypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ typedef unsigned useconds_t;
264264

265265
#ifdef __cplusplus
266266
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
267-
typedef unsigned long pthread_t;
267+
typedef unsigned _Addr pthread_t;
268268
#define __DEFINED_pthread_t
269269
#endif
270270

musl-generated/x86_64/bits/alltypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ typedef unsigned useconds_t;
264264

265265
#ifdef __cplusplus
266266
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
267-
typedef unsigned long pthread_t;
267+
typedef unsigned _Addr pthread_t;
268268
#define __DEFINED_pthread_t
269269
#endif
270270

0 commit comments

Comments
 (0)