Skip to content

Case 107: task_scheduler_init Removed (historical ABI break)

Field Value
Verdict ๐Ÿ”ด BREAKING
Category Breaking
Platforms Linux, macOS, Windows
Flags ABI break, API break
Detected ChangeKinds func_removed, type_removed
Source files examples/case107_task_scheduler_init_removed/

Category: Class Removal | Verdict: ๐Ÿ”ด BREAKING

What breaks

An entire publicly-exported class โ€” task_scheduler_init โ€” is removed in v2. Every consumer that referenced the class (constructed it, called its members, or held it by value) gets undefined symbol at load time, and source code fails to compile against the new headers.

Real Failure Demo

Severity: BREAKING

cmake -S examples -B /tmp/abicheck-examples-build -DCMAKE_BUILD_TYPE=Debug
cmake --build /tmp/abicheck-examples-build \
  --target case107_task_scheduler_init_removed_app case107_task_scheduler_init_removed_v2

/tmp/abicheck-examples-build/case107_task_scheduler_init_removed/app_v1
# active = 1 (expect 1)
# active = 0 (expect 0)

# Runtime replacement: a binary linked against v1 fails when v2 is substituted
# under the old library name.
tmp=$(mktemp -d)
cp /tmp/abicheck-examples-build/case107_task_scheduler_init_removed/app_v1 "$tmp/"
cp /tmp/abicheck-examples-build/case107_task_scheduler_init_removed/libv2.so "$tmp/libv1.so"
(cd "$tmp" && LD_LIBRARY_PATH=. ./app_v1)
# ./app_v1: symbol lookup error: ./app_v1: undefined symbol: _ZN5mylib19task_scheduler_initD1Ev

# Source rebuild against the v2 header also fails because the class is gone.
tmp=$(mktemp -d)
cp examples/case107_task_scheduler_init_removed/app.cpp "$tmp/app.cpp"
cp examples/case107_task_scheduler_init_removed/v2.h "$tmp/v1.h"
g++ -std=c++17 -I"$tmp" -c "$tmp/app.cpp" -o "$tmp/app.o"
# error: 'task_scheduler_init' is not a member of 'mylib'

Why this matters

This fixture mirrors the single largest hard ABI break in TBB's history: classic TBB deprecated tbb::task_scheduler_init in 2020 and removed it in oneTBB 2021.1, alongside the entire tbb::task low-level API. The replacements (tbb::global_control, tbb::task_arena) have different lifetimes and semantics.

Real-world consequence: every Boost build that linked TBB, every HPC code using task_scheduler_init directly, and every downstream package had to either pin to classic TBB or rewrite its initialization path.

Code diff

v1 v2
class task_scheduler_init { ... }; (removed)
task_scheduler_init(int) (removed)
terminate() / is_active() (removed)

How abicheck catches it

The existing FUNC_REMOVED / TYPE_REMOVED detectors fire on every public symbol the class exported. This case exists as a named regression fixture so the canonical TBB removal pattern stays exercised in CI.

How to fix

Don't remove publicly-exported classes in a minor release. The oneTBB migration showed the only safe path: 1. Major SONAME bump (libtbb.so.2 โ†’ libtbb.so.12). 2. Concurrent shipping of compatibility headers via a separate package (tbb_preview) for a transition release. 3. Strong documentation of the migration with mechanical replacements.

References


Source files

  • CMakeLists.txt
  • app.cpp
  • v1.cpp
  • v1.h
  • v2.cpp
  • v2.h

See also: Examples overview ยท All BREAKING cases ยท Category: Breaking.