https://github.com/python/cpython/commit/25243b1461e524560639ebe54bab9b689b6cc31e
commit: 25243b1461e524560639ebe54bab9b689b6cc31e
branch: 3.12
author: Antoine Pitrou <anto...@python.org>
committer: pitrou <pit...@free.fr>
date: 2024-03-18T09:52:54Z
summary:

[3.12] gh-112536: Add TSAN build on Github Actions (GH-116872)

(cherry picked from commit 20578a1f68c841a264b72b00591b11ab2fa77b43)

Co-authored-by: Donghee Na <donghee...@python.org>

files:
A .github/workflows/reusable-tsan.yml
M .github/workflows/build.yml
M Lib/test/test_concurrent_futures/util.py
M Lib/test/test_logging.py
M Python/thread_pthread.h

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d9c399476e24a6..cd56c7d84ab8f1 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -471,6 +471,15 @@ jobs:
     - name: Tests
       run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu"
 
+  build_tsan:
+    name: 'Thread sanitizer'
+    needs: check_source
+    if: needs.check_source.outputs.run_tests == 'true'
+    uses: ./.github/workflows/reusable-tsan.yml
+    with:
+      config_hash: ${{ needs.check_source.outputs.config_hash }}
+      options: ./configure --config-cache --with-thread-sanitizer 
--with-pydebug
+
   all-required-green:  # This job does nothing and is only used for the branch 
protection
     name: All required checks pass
     if: always()
@@ -485,6 +494,7 @@ jobs:
     - build_windows
     - test_hypothesis
     - build_asan
+    - build_tsan
 
     runs-on: ubuntu-latest
 
@@ -513,6 +523,7 @@ jobs:
             build_ubuntu_ssltests,
             build_windows,
             build_asan,
+            build_tsan,
             '
             || ''
           }}
diff --git a/.github/workflows/reusable-tsan.yml 
b/.github/workflows/reusable-tsan.yml
new file mode 100644
index 00000000000000..96a9c1b0cda3c3
--- /dev/null
+++ b/.github/workflows/reusable-tsan.yml
@@ -0,0 +1,51 @@
+on:
+  workflow_call:
+    inputs:
+      config_hash:
+        required: true
+        type: string
+      options:
+        required: true
+        type: string
+
+jobs:
+  build_tsan_reusable:
+    name: 'Thread sanitizer'
+    runs-on: ubuntu-22.04
+    timeout-minutes: 60
+    steps:
+    - uses: actions/checkout@v4
+    - name: Runner image version
+      run: echo "IMAGE_VERSION=${ImageVersion}" >> $GITHUB_ENV
+    - name: Restore config.cache
+      uses: actions/cache@v4
+      with:
+        path: config.cache
+        key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ 
inputs.config_hash }}
+    - name: Install Dependencies
+      run: |
+        sudo ./.github/workflows/posix-deps-apt.sh
+        sudo apt install -y clang
+        # Reduce ASLR to avoid TSAN crashing
+        sudo sysctl -w vm.mmap_rnd_bits=28
+    - name: TSAN Option Setup
+      run: |
+        echo 
"TSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/Tools/tsan/supressions.txt" >> 
$GITHUB_ENV
+        echo "CC=clang" >> $GITHUB_ENV
+        echo "CXX=clang++" >> $GITHUB_ENV
+    - name: Add ccache to PATH
+      run: |
+        echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
+    - name: Configure ccache action
+      uses: hendrikmuhs/ccache-action@v1.2
+      with:
+        save: ${{ github.event_name == 'push' }}
+        max-size: "200M"
+    - name: Configure CPython
+      run: ${{ inputs.options }}
+    - name: Build CPython
+      run: make -j4
+    - name: Display build info
+      run: make pythoninfo
+    - name: Tests
+      run: ./python -m test --tsan -j4
diff --git a/Lib/test/test_concurrent_futures/util.py 
b/Lib/test/test_concurrent_futures/util.py
index dc48bec796b87f..fc6030e375fb6b 100644
--- a/Lib/test/test_concurrent_futures/util.py
+++ b/Lib/test/test_concurrent_futures/util.py
@@ -85,6 +85,8 @@ def get_context(self):
             self.skipTest("ProcessPoolExecutor unavailable on this system")
         if sys.platform == "win32":
             self.skipTest("require unix system")
+        if support.check_sanitizer(thread=True):
+            self.skipTest("TSAN doesn't support threads after fork")
         return super().get_context()
 
 
@@ -111,6 +113,8 @@ def get_context(self):
             self.skipTest("ProcessPoolExecutor unavailable on this system")
         if sys.platform == "win32":
             self.skipTest("require unix system")
+        if support.check_sanitizer(thread=True):
+            self.skipTest("TSAN doesn't support threads after fork")
         return super().get_context()
 
 
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 463bbc575c7275..6bff48c39df7b8 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -80,6 +80,9 @@
 skip_if_asan_fork = unittest.skipIf(
     support.HAVE_ASAN_FORK_BUG,
     "libasan has a pthread_create() dead lock related to thread+fork")
+skip_if_tsan_fork = unittest.skipIf(
+    support.check_sanitizer(thread=True),
+    "TSAN doesn't support threads after fork")
 
 
 class BaseTest(unittest.TestCase):
@@ -737,6 +740,7 @@ def remove_loop(fname, tries):
     @support.requires_fork()
     @threading_helper.requires_working_threading()
     @skip_if_asan_fork
+    @skip_if_tsan_fork
     def test_post_fork_child_no_deadlock(self):
         """Ensure child logging locks are not held; bpo-6721 & bpo-36533."""
         class _OurHandler(logging.Handler):
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index f96c57da64636d..896230d9831180 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -91,6 +91,10 @@
 #endif
 #endif
 
+/* Thread sanitizer doesn't currently support sem_clockwait */
+#ifdef _Py_THREAD_SANITIZER
+#undef HAVE_SEM_CLOCKWAIT
+#endif
 
 /* Whether or not to use semaphores directly rather than emulating them with
  * mutexes and condition variables:

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to