Skip to content

Commit 069e4bd

Browse files
authored
Merge branch 'main' into set-ar-program
2 parents a2d5fb0 + c103179 commit 069e4bd

File tree

18 files changed

+336
-38
lines changed

18 files changed

+336
-38
lines changed

.github/workflows/main.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ jobs:
1616
strategy:
1717
matrix:
1818
include:
19+
- name: aarch64-unknown-linux-gnu
20+
target: aarch64-unknown-linux-gnu
21+
nobgt: 0
22+
no_tests: 1
23+
tag: ubuntu-24.04-arm
1924
- name: x86_64-apple-darwin
2025
target: x86_64-apple-darwin
2126
nobgt: 0

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
# 0.6.1 - 2025-10-15
2+
3+
- Fix compiler and clippy warnings (#105)
4+
- Add feature `disable_cache_oblivious` to jemallocator re-exports (#104)
5+
- Document `JEMALLOC_OVERRIDE` (#107)
6+
- Harden `strerror_r` function detection (#117)
7+
- Respect jobserver set by Cargo (#120)
8+
- Make unprefixed consistently override the system allocator (#109)
9+
- Adds new Cargo feature `override_allocator_on_supported_platforms`.
10+
- `cat` the entire `config.log` (#142)
11+
112
# 0.6.0 - 2024-07-14
213

314
- Fix build on riscv64gc-unknown-linux-musl (#67) (#75)

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
[workspace]
2-
members = ["jemallocator", "jemallocator-global", "jemalloc-ctl", "jemalloc-sys"]
2+
members = [
3+
"jemallocator",
4+
"jemallocator-global",
5+
"jemalloc-ctl",
6+
"jemalloc-sys",
7+
"test-dylib",
8+
]

ci/run.sh

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ cargo test --target "${TARGET}" --features stats
3232
cargo test --target "${TARGET}" --features 'debug profiling'
3333

3434
cargo test --target "${TARGET}" \
35-
--features unprefixed_malloc_on_supported_platforms
35+
--features override_allocator_on_supported_platforms
3636
cargo test --target "${TARGET}" --no-default-features
3737
cargo test --target "${TARGET}" --no-default-features \
3838
--features background_threads_runtime_support
@@ -48,7 +48,7 @@ cargo test --target "${TARGET}" --release
4848
cargo test --target "${TARGET}" --manifest-path jemalloc-sys/Cargo.toml
4949
cargo test --target "${TARGET}" \
5050
--manifest-path jemalloc-sys/Cargo.toml \
51-
--features unprefixed_malloc_on_supported_platforms
51+
--features override_allocator_on_supported_platforms
5252

5353
# FIXME: jemalloc-ctl fails in the following targets
5454
case "${TARGET}" in
@@ -77,3 +77,14 @@ cargo test --target "${TARGET}" \
7777
# # The Alloc trait is unstable:
7878
# ${CARGO_CMD} test --target "${TARGET}" --features alloc_trait
7979
# fi
80+
81+
# Test that overriding works in dylibs.
82+
case "$TARGET" in
83+
"i686-unknown-linux-musl") ;;
84+
"x86_64-unknown-linux-musl") ;;
85+
*)
86+
cargo run --target "${TARGET}" \
87+
-p test-dylib \
88+
--features override_allocator_on_supported_platforms
89+
;;
90+
esac

jemalloc-ctl/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tikv-jemalloc-ctl"
3-
version = "0.6.0"
3+
version = "0.6.1"
44
authors = [
55
"Steven Fackler <sfackler@gmail.com>",
66
"Gonzalo Brito Gadeschi <gonzalobg88@gmail.com>",
@@ -26,12 +26,12 @@ is-it-maintained-open-issues = { repository = "tikv/jemallocator" }
2626
maintenance = { status = "actively-developed" }
2727

2828
[dependencies]
29-
tikv-jemalloc-sys = { path = "../jemalloc-sys", version = "0.6.0" }
29+
tikv-jemalloc-sys = { path = "../jemalloc-sys", version = "0.6.1" }
3030
libc = { version = "0.2", default-features = false }
3131
paste = "1"
3232

3333
[dev-dependencies]
34-
tikv-jemallocator = { path = "../jemallocator", version = "0.6.0" }
34+
tikv-jemallocator = { path = "../jemallocator", version = "0.6.1" }
3535

3636
[features]
3737
default = []

jemalloc-sys/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tikv-jemalloc-sys"
3-
version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7"
3+
version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7"
44
authors = [
55
"Alex Crichton <alex@alexcrichton.com>",
66
"Gonzalo Brito Gadeschi <gonzalobg88@gmail.com>",
@@ -46,6 +46,7 @@ background_threads_runtime_support = []
4646
background_threads = [ "background_threads_runtime_support" ]
4747
stats = []
4848
unprefixed_malloc_on_supported_platforms = []
49+
override_allocator_on_supported_platforms = [ "unprefixed_malloc_on_supported_platforms" ]
4950
disable_initial_exec_tls = []
5051
disable_cache_oblivious = []
5152

jemalloc-sys/README.md

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ This crate provides following cargo feature flags:
4848
* `stats` (configure `jemalloc` with `--enable-stats`): Enable statistics
4949
gathering functionality. See the `jemalloc`'s "`opt.stats_print`" option
5050
documentation for usage details.
51-
51+
5252
* `debug` (configure `jemalloc` with `--enable-debug`): Enable assertions and
5353
validation code. This incurs a substantial performance hit, but is very useful
5454
during application development.
55-
55+
5656
* `background_threads_runtime_support` (enabled by default): enables
5757
background-threads run-time support when building `jemalloc-sys` on some POSIX
5858
targets supported by `jemalloc`. Background threads are disabled at run-time
@@ -72,16 +72,33 @@ This crate provides following cargo feature flags:
7272
* `unprefixed_malloc_on_supported_platforms`: when disabled, configure
7373
`jemalloc` with `--with-jemalloc-prefix=_rjem_`. Enabling this causes symbols
7474
like `malloc` to be emitted without a prefix, overriding the ones defined by
75-
libc. This usually causes C and C++ code linked in the same program to use
76-
`jemalloc` as well. On some platforms prefixes are always used because
77-
unprefixing is known to cause segfaults due to allocator mismatches.
78-
75+
libc. This usually causes C, Objective-C and C++ code linked in the same
76+
program to use `jemalloc` as well. On some platforms prefixes are always used
77+
because unprefixing is known to cause segfaults due to allocator mismatches.
78+
79+
* `override_allocator_on_supported_platforms`: override the system allocator,
80+
even outside Rust code.
81+
82+
This enables the `unprefixed_malloc_on_supported_platforms` feature, with the
83+
addition that it forces overriding the allocator even if `malloc` and `free`
84+
would not usually have been seen by the linker. It also overrides the
85+
allocator on Apple platforms.
86+
87+
Note that to use this, the `jemalloc-sys` crate must actually be visible to
88+
`rustc` (it is not enough to only declare it in `Cargo.toml`). This can be
89+
done by adding:
90+
```rust
91+
use jemalloc_sys as _;
92+
```
93+
94+
In your `main.rs`.
95+
7996
* `disable_initial_exec_tls` (disabled by default): when enabled, jemalloc is
80-
built with the `--disable-initial-exec-tls` option. It disables the
81-
initial-exec TLS model for jemalloc's internal thread-local storage (on those
82-
platforms that support explicit settings). This can allow jemalloc to be
97+
built with the `--disable-initial-exec-tls` option. It disables the
98+
initial-exec TLS model for jemalloc's internal thread-local storage (on those
99+
platforms that support explicit settings). This can allow jemalloc to be
83100
dynamically loaded after program startup (e.g. using dlopen). If you encounter
84-
the error `yourlib.so: cannot allocate memory in static TLS block`, you'll
101+
the error `yourlib.so: cannot allocate memory in static TLS block`, you'll
85102
likely want to enable this.
86103

87104
* `disable_cache_oblivious` (disabled by default): when enabled, jemalloc is
@@ -104,7 +121,7 @@ hyphens `-` are replaced with underscores `_`(see
104121
variable, the `/etc/malloc.conf` symlink, and the `MALLOC_CONF` environment
105122
variable (note: this variable might be prefixed as `_RJEM_MALLOC_CONF`). For
106123
example, to change the default decay time for dirty pages to 30 seconds:
107-
124+
108125
```
109126
JEMALLOC_SYS_WITH_MALLOC_CONF=dirty_decay_ms:30000
110127
```
@@ -115,17 +132,17 @@ hyphens `-` are replaced with underscores `_`(see
115132
allocator page size equal to the system page size, so this option need not be
116133
specified unless the system page size may change between configuration and
117134
execution, e.g. when cross compiling.
118-
135+
119136
* `JEMALLOC_SYS_WITH_LG_HUGEPAGE=<lg-hugepage>`: Specify the base 2 log of the
120137
system huge page size. This option is useful when cross compiling, or when
121138
overriding the default for systems that do not explicitly support huge pages.
122-
123-
139+
140+
124141
* `JEMALLOC_SYS_WITH_LG_QUANTUM=<lg-quantum>`: Specify the base 2 log of the
125142
minimum allocation alignment. jemalloc needs to know the minimum alignment
126143
that meets the following C standard requirement (quoted from the April 12,
127144
2011 draft of the C11 standard):
128-
145+
129146
> The pointer returned if the allocation succeeds is suitably aligned so that
130147
> it may be assigned to a pointer to any type of object with a fundamental
131148
> alignment requirement and then used to access such an object or an array of

jemalloc-sys/build.rs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,16 @@ fn main() {
111111
.iter()
112112
.any(|i| target.contains(i))
113113
{
114-
warning!(
115-
"Unprefixed `malloc` requested on unsupported platform `{}` => using prefixed `malloc`",
116-
target
117-
);
114+
// Apple targets don't support unprefixed, but they do support
115+
// overriding (if you do the `zone_register` trick), so no need to
116+
// warn there.
117+
let override_ = env::var("CARGO_FEATURE_OVERRIDE_ALLOCATOR_ON_SUPPORTED_PLATFORMS").is_ok();
118+
if !target.contains("apple") || !override_ {
119+
warning!(
120+
"Unprefixed `malloc` requested on unsupported platform `{}` => using prefixed `malloc`",
121+
target
122+
);
123+
}
118124
use_prefix = true;
119125
}
120126

@@ -326,6 +332,9 @@ fn main() {
326332
.arg("install_lib_static")
327333
.arg("install_include"));
328334

335+
// Try to remove the build directory to avoid it wasting disk space in the target directory
336+
let _ = fs::remove_dir_all(build_dir);
337+
329338
println!("cargo:root={}", out_dir.display());
330339

331340
// Linkage directives to pull in jemalloc and its dependencies.
@@ -340,7 +349,7 @@ fn main() {
340349
} else {
341350
println!("cargo:rustc-link-lib=static=jemalloc_pic");
342351
}
343-
println!("cargo:rustc-link-search=native={}/lib", build_dir.display());
352+
println!("cargo:rustc-link-search=native={}/lib", out_dir.display());
344353
if target.contains("android") {
345354
println!("cargo:rustc-link-lib=gcc");
346355
} else if !target.contains("windows") {
@@ -370,7 +379,10 @@ fn make_command(make_cmd: &str, build_dir: &Path, num_jobs: &str) -> Command {
370379

371380
if let Ok(makeflags) = std::env::var("CARGO_MAKEFLAGS") {
372381
let makeflags = if let Ok(orig_makeflags) = std::env::var("MAKEFLAGS") {
373-
format!("{orig_makeflags} {makeflags}")
382+
// Prepend Cargo makeflags before externally configured makeflags
383+
// Adding Cargo makeflags at the end was causing issues, see
384+
// https://github.com/tikv/jemallocator/issues/92#issuecomment-3536269176.
385+
format!("{makeflags} {orig_makeflags}")
374386
} else {
375387
makeflags
376388
};
@@ -383,7 +395,14 @@ fn make_command(make_cmd: &str, build_dir: &Path, num_jobs: &str) -> Command {
383395

384396
fn run_and_log(cmd: &mut Command, log_file: &Path) {
385397
execute(cmd, || {
386-
run(Command::new("tail").arg("-n").arg("100").arg(log_file));
398+
// In CI systems print the whole log since it can be difficult to get to
399+
// a log file after the build fails. Otherwise print the last 100 lines
400+
// to keep the output concise.
401+
if env::var_os("CI").is_some() {
402+
run(Command::new("cat").arg(log_file));
403+
} else {
404+
run(Command::new("tail").arg("-n").arg("100").arg(log_file));
405+
}
387406
})
388407
}
389408

@@ -411,10 +430,13 @@ fn gnu_target(target: &str) -> String {
411430
match target {
412431
"i686-pc-windows-msvc" => "i686-pc-win32".to_string(),
413432
"x86_64-pc-windows-msvc" => "x86_64-pc-win32".to_string(),
414-
"i686-pc-windows-gnu" => "i686-w64-mingw32".to_string(),
415-
"x86_64-pc-windows-gnu" => "x86_64-w64-mingw32".to_string(),
433+
"i686-pc-windows-gnu" | "i686-pc-windows-gnullvm" => "i686-w64-mingw32".to_string(),
434+
"x86_64-pc-windows-gnu" | "x86_64-pc-windows-gnullvm" => "x86_64-w64-mingw32".to_string(),
435+
"aarch64-pc-windows-gnullvm" => "aarch64-w64-mingw32".to_string(),
416436
"armv7-linux-androideabi" => "arm-linux-androideabi".to_string(),
417-
"riscv64gc-unknown-linux-gnu" => "riscv64-linux-gnu".to_string(),
437+
"riscv64gc-unknown-linux-gnu" | "riscv64a23-unknown-linux-gnu" => {
438+
"riscv64-linux-gnu".to_string()
439+
}
418440
"riscv64gc-unknown-linux-musl" => "riscv64-linux-musl".to_string(),
419441
s => s.to_string(),
420442
}

jemalloc-sys/src/env.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ pub static NO_BG_THREAD_TARGETS: &[&str] = &["musl"];
2121
// https://github.com/rust-lang/rust/commit/e3b414d8612314e74e2b0ebde1ed5c6997d28e8d
2222
// https://github.com/rust-lang/rust/commit/9f3de647326fbe50e0e283b9018ab7c41abccde3
2323
// https://github.com/rust-lang/rust/commit/ed015456a114ae907a36af80c06f81ea93182a24
24-
pub static NO_UNPREFIXED_MALLOC_TARGETS: &[&str] = &["android", "dragonfly", "darwin"];
24+
pub static NO_UNPREFIXED_MALLOC_TARGETS: &[&str] = &["android", "dragonfly", "apple"];

jemalloc-sys/src/lib.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,3 +890,86 @@ pub type extent_merge_t = unsafe extern "C" fn(
890890
mod env;
891891

892892
pub use env::*;
893+
894+
// When using the `"override_allocator_on_supported_platforms"` feature flag,
895+
// the user wants us to globally override the system allocator.
896+
//
897+
// However, since we build `jemalloc` as a static library (an archive), the
898+
// linker may decide to not care about our overrides if it can't directly see
899+
// references to the symbols, see the following link for details:
900+
// <https://maskray.me/blog/2021-06-20-symbol-processing#archive-processing>
901+
//
902+
// This is problematic if `jemalloc_sys` is used from a library that by itself
903+
// doesn't allocate, while invoking other shared libraries that do.
904+
//
905+
// Another especially problematic case would be something like the following:
906+
//
907+
// ```
908+
// // Call `malloc` whose symbol is looked up statically.
909+
// let ptr = libc::malloc(42);
910+
//
911+
// // But use a dynamically looked up `free`.
912+
// let free = libc::dlsym(null_mut(), c"free".as_ptr());
913+
// let free = transmute::<*mut c_void, unsafe extern "C" fn(*mut c_void)>(free);
914+
// free(ptr);
915+
// ```
916+
//
917+
// Since if the `malloc` and `free` provided by `jemalloc` end up in different
918+
// object files in the archive (NOTE: In practice, this is unlikely to be an
919+
// issue, since `jemalloc.c` contains all the implementations and is compiled
920+
// as a single object file), the linker would think that only `malloc` was
921+
// used, and would never load the `free` that we also want (and hence we'd end
922+
// up executing jemalloc's `malloc` and the system's `free`, which is UB).
923+
//
924+
// To avoid this problem, we make sure that all the allocator functions are
925+
// visible to the linker, such that it will always override all of them.
926+
//
927+
// We do this by referencing these symbols in `#[used]` statics, which makes
928+
// them known to `rustc`, which will reference them in a `symbols.o` stub file
929+
// that is later passed to the linker. See the following link for details on
930+
// how this works:
931+
// <https://github.com/rust-lang/rust/pull/95604>
932+
933+
#[cfg(all(
934+
feature = "override_allocator_on_supported_platforms",
935+
not(target_vendor = "apple")
936+
))]
937+
mod set_up_statics {
938+
use super::*;
939+
940+
#[used]
941+
static USED_MALLOC: unsafe extern "C" fn(usize) -> *mut c_void = malloc;
942+
#[used]
943+
static USED_CALLOC: unsafe extern "C" fn(usize, usize) -> *mut c_void = calloc;
944+
#[used]
945+
static USED_POSIX_MEMALIGN: unsafe extern "C" fn(*mut *mut c_void, usize, usize) -> c_int =
946+
posix_memalign;
947+
#[used]
948+
static USED_ALIGNED_ALLOC: unsafe extern "C" fn(usize, usize) -> *mut c_void = aligned_alloc;
949+
#[used]
950+
static USED_REALLOC: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = realloc;
951+
#[used]
952+
static USED_FREE: unsafe extern "C" fn(*mut c_void) = free;
953+
}
954+
955+
// On macOS, jemalloc doesn't directly override malloc/free, but instead
956+
// registers itself with the allocator's zone APIs in a ctor (`zone_register`
957+
// is marked with `__attribute__((constructor))`).
958+
//
959+
// Similarly to above though, for the Mach-O linker to actually consider ctors
960+
// as "used" when defined in an archive member in a static library, so we need
961+
// to explicitly reference the function via. Rust's `#[used]`.
962+
963+
#[cfg(all(
964+
feature = "override_allocator_on_supported_platforms",
965+
target_vendor = "apple"
966+
))]
967+
#[used]
968+
static USED_ZONE_REGISTER: unsafe extern "C" fn() = {
969+
extern "C" {
970+
#[cfg_attr(prefixed, link_name = "_rjem_je_zone_register")]
971+
#[cfg_attr(not(prefixed), link_name = "je_zone_register")]
972+
fn zone_register();
973+
}
974+
zone_register
975+
};

0 commit comments

Comments
 (0)