@@ -19,6 +19,7 @@ concurrency:
1919env :
2020 BITCOIN_REPO : bitcoin/bitcoin
2121 LLVM_VERSION : 22
22+ LIBCXX_DIR : /tmp/libcxx-build/
2223
2324jobs :
2425 bitcoin-core :
@@ -160,3 +161,199 @@ jobs:
160161 with :
161162 path : ${{ env.CCACHE_DIR }}
162163 key : ccache-${{ matrix.name }}-${{ github.ref }}-${{ github.sha }}
164+
165+ bitcoin-core-tsan :
166+ name : TSan
167+ runs-on : ubuntu-24.04
168+ timeout-minutes : 180
169+
170+ env :
171+ CCACHE_MAXSIZE : 400M
172+ CCACHE_DIR : ${{ github.workspace }}/.ccache
173+ LIBCXX_FLAGS : >-
174+ -fsanitize=thread
175+ -nostdinc++
176+ -nostdlib++
177+ -isystem /tmp/libcxx-build/include/c++/v1
178+ -L/tmp/libcxx-build/lib
179+ -Wl,-rpath,/tmp/libcxx-build/lib
180+ -lc++
181+ -lc++abi
182+ -lpthread
183+ -Wno-unused-command-line-argument
184+ TSAN_OPTIONS : suppressions=${{ github.workspace }}/test/sanitizer_suppressions/tsan:halt_on_error=1:second_deadlock_stack=1
185+
186+ steps :
187+ - name : Checkout Bitcoin Core
188+ uses : actions/checkout@v4
189+ with :
190+ repository : ${{ env.BITCOIN_REPO }}
191+ fetch-depth : 1
192+
193+ - name : Add LLVM apt repository
194+ run : |
195+ curl -s "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo tee "/etc/apt/trusted.gpg.d/apt.llvm.org.asc" > /dev/null
196+ source /etc/os-release
197+ echo "deb http://apt.llvm.org/${VERSION_CODENAME}/ llvm-toolchain-${VERSION_CODENAME}-${LLVM_VERSION} main" | sudo tee "/etc/apt/sources.list.d/llvm.list"
198+ sudo apt-get update
199+
200+ - name : Install packages
201+ run : |
202+ sudo apt-get install --no-install-recommends -y \
203+ "clang-${LLVM_VERSION}" \
204+ "llvm-${LLVM_VERSION}" \
205+ "llvm-${LLVM_VERSION}-dev" \
206+ "libclang-${LLVM_VERSION}-dev" \
207+ "libclang-rt-${LLVM_VERSION}-dev" \
208+ ninja-build \
209+ pkgconf \
210+ python3-pip \
211+ bison
212+ sudo update-alternatives --install /usr/bin/clang++ clang++ "/usr/bin/clang++-${LLVM_VERSION}" 100
213+ sudo update-alternatives --install /usr/bin/clang clang "/usr/bin/clang-${LLVM_VERSION}" 100
214+ sudo update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer "/usr/bin/llvm-symbolizer-${LLVM_VERSION}" 100
215+ sudo update-alternatives --set clang "/usr/bin/clang-${LLVM_VERSION}"
216+ sudo update-alternatives --set clang++ "/usr/bin/clang++-${LLVM_VERSION}"
217+ sudo update-alternatives --set llvm-symbolizer "/usr/bin/llvm-symbolizer-${LLVM_VERSION}"
218+ pip3 install --break-system-packages pycapnp
219+
220+ - name : Restore instrumented libc++ cache
221+ id : libcxx-cache
222+ uses : actions/cache@v4
223+ with :
224+ path : ${{ env.LIBCXX_DIR }}
225+ key : libcxx-Thread-llvmorg-${{ env.LLVM_VERSION }}.1.0
226+
227+ - name : Build instrumented libc++
228+ if : steps.libcxx-cache.outputs.cache-hit != 'true'
229+ run : |
230+ export PATH="/usr/lib/llvm-${LLVM_VERSION}/bin:$PATH"
231+ ls -l /usr/bin/clang /usr/bin/clang++ /usr/bin/llvm-symbolizer
232+ which clang clang++ llvm-symbolizer
233+ clang --version
234+ clang++ --version
235+ "/usr/bin/clang-${LLVM_VERSION}" --version
236+ "/usr/bin/clang++-${LLVM_VERSION}" --version
237+ git clone --depth=1 https://github.com/llvm/llvm-project -b "llvmorg-${LLVM_VERSION}.1.0" /tmp/llvm-project
238+ cmake -G Ninja -B "$LIBCXX_DIR" \
239+ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \
240+ -DCMAKE_BUILD_TYPE=Release \
241+ -DLLVM_USE_SANITIZER=Thread \
242+ -DCMAKE_C_COMPILER="/usr/bin/clang-${LLVM_VERSION}" \
243+ -DCMAKE_CXX_COMPILER="/usr/bin/clang++-${LLVM_VERSION}" \
244+ -DLLVM_TARGETS_TO_BUILD=Native \
245+ -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF \
246+ -DLIBCXX_INCLUDE_TESTS=OFF \
247+ -DLIBCXXABI_INCLUDE_TESTS=OFF \
248+ -DLIBUNWIND_INCLUDE_TESTS=OFF \
249+ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \
250+ -S /tmp/llvm-project/runtimes
251+ grep -E 'CMAKE_(C|CXX)_COMPILER' "$LIBCXX_DIR/CMakeCache.txt"
252+ ninja -C "$LIBCXX_DIR" "-j$(nproc)" -v
253+ rm -rf /tmp/llvm-project
254+
255+ - name : Determine host
256+ id : host
257+ run : echo "host=$(./depends/config.guess)" >> "$GITHUB_OUTPUT"
258+
259+ - name : Restore depends cache
260+ id : depends-cache
261+ uses : actions/cache/restore@v4
262+ with :
263+ path : |
264+ depends/built
265+ depends/${{ steps.host.outputs.host }}
266+ key : depends-tsan-${{ hashFiles('depends/packages/*.mk') }}-${{ env.LLVM_VERSION }}
267+
268+ - name : Build depends (stage 1, without IPC)
269+ if : steps.depends-cache.outputs.cache-hit != 'true'
270+ run : |
271+ make -C depends "-j$(nproc)" \
272+ CC=clang \
273+ CXX=clang++ \
274+ CXXFLAGS="${LIBCXX_FLAGS}" \
275+ NO_QT=1 \
276+ NO_ZMQ=1 \
277+ NO_USDT=1 \
278+ NO_QR=1 \
279+ NO_IPC=1
280+
281+ - name : Save depends cache
282+ uses : actions/cache/save@v4
283+ if : steps.depends-cache.outputs.cache-hit != 'true'
284+ with :
285+ path : |
286+ depends/built
287+ depends/${{ steps.host.outputs.host }}
288+ key : depends-tsan-${{ hashFiles('depends/packages/*.mk') }}-${{ env.LLVM_VERSION }}
289+
290+ - name : Checkout libmultiprocess
291+ uses : actions/checkout@v4
292+ with :
293+ path : _libmultiprocess
294+
295+ - name : Replace libmultiprocess subtree
296+ run : |
297+ rm -rf src/ipc/libmultiprocess
298+ mv _libmultiprocess src/ipc/libmultiprocess
299+
300+ - name : Build depends (stage 2, IPC packages including libmultiprocess)
301+ run : |
302+ make -C depends "-j$(nproc)" \
303+ CC=clang \
304+ CXX=clang++ \
305+ CXXFLAGS="${LIBCXX_FLAGS}" \
306+ NO_QT=1 \
307+ NO_ZMQ=1 \
308+ NO_USDT=1 \
309+ NO_QR=1
310+
311+ - name : Restore ccache
312+ id : ccache-restore
313+ uses : actions/cache/restore@v4
314+ with :
315+ path : ${{ env.CCACHE_DIR }}
316+ key : ccache-TSan-${{ github.ref }}-${{ github.sha }}
317+ restore-keys : |
318+ ccache-TSan-${{ github.ref }}-
319+ ccache-TSan-
320+
321+ - name : CMake configure
322+ run : |
323+ cmake -S . -B build \
324+ --preset=dev-mode \
325+ -DCMAKE_BUILD_TYPE=Debug \
326+ -DBUILD_GUI=OFF \
327+ -DBUILD_GUI_TESTS=OFF \
328+ -DWITH_ZMQ=OFF \
329+ -DWITH_USDT=OFF \
330+ -DBUILD_BENCH=OFF \
331+ -DBUILD_FUZZ_BINARY=OFF \
332+ -DWITH_QRENCODE=OFF \
333+ -DSANITIZERS=thread \
334+ -DAPPEND_CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKCONTENTION -D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES' \
335+ -DCMAKE_TOOLCHAIN_FILE=depends/${{ steps.host.outputs.host }}/toolchain.cmake \
336+ -G Ninja
337+
338+ - name : Build
339+ run : cmake --build build "-j$(nproc)"
340+
341+ - name : Run IPC and miner unit tests
342+ run : |
343+ ctest --test-dir build --tests-regex "ipc|miner_tests" --output-on-failure --timeout 480
344+
345+ - name : Run IPC functional tests
346+ run : |
347+ tests=()
348+ for _ in $(seq 1 20); do
349+ tests+=(interface_ipc)
350+ done
351+ LD_LIBRARY_PATH="depends/${{ steps.host.outputs.host }}/lib" \
352+ build/test/functional/test_runner.py -j "$(nproc)" "${tests[@]}" --timeout-factor=10
353+
354+ - name : Save ccache
355+ uses : actions/cache/save@v4
356+ if : github.ref == 'refs/heads/master' || steps.ccache-restore.outputs.cache-hit != 'true'
357+ with :
358+ path : ${{ env.CCACHE_DIR }}
359+ key : ccache-TSan-${{ github.ref }}-${{ github.sha }}
0 commit comments