Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 5dc7977

Browse filesBrowse files
committed
Merge branch 'main' into close-escapes-2
2 parents 3369849 + 6c63afc commit 5dc7977
Copy full SHA for 5dc7977

File tree

Expand file treeCollapse file tree

111 files changed

+1583
-979
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

111 files changed

+1583
-979
lines changed

‎.github/workflows/build.yml

Copy file name to clipboardExpand all lines: .github/workflows/build.yml
+45-14Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -512,26 +512,59 @@ jobs:
512512
run: xvfb-run make ci
513513

514514
build_tsan:
515-
name: 'Thread sanitizer'
515+
name: >-
516+
Thread sanitizer
517+
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
516518
needs: check_source
517519
if: needs.check_source.outputs.run_tests == 'true'
520+
strategy:
521+
matrix:
522+
free-threading:
523+
- false
524+
- true
518525
uses: ./.github/workflows/reusable-tsan.yml
519526
with:
520527
config_hash: ${{ needs.check_source.outputs.config_hash }}
521-
options: ./configure --config-cache --with-thread-sanitizer --with-pydebug
522-
suppressions_path: Tools/tsan/supressions.txt
523-
tsan_logs_artifact_name: tsan-logs-default
528+
free-threading: ${{ matrix.free-threading }}
524529

525-
build_tsan_free_threading:
526-
name: 'Thread sanitizer (free-threading)'
530+
cross-build-linux:
531+
name: Cross build Linux
532+
runs-on: ubuntu-latest
527533
needs: check_source
528534
if: needs.check_source.outputs.run_tests == 'true'
529-
uses: ./.github/workflows/reusable-tsan.yml
530-
with:
531-
config_hash: ${{ needs.check_source.outputs.config_hash }}
532-
options: ./configure --config-cache --disable-gil --with-thread-sanitizer --with-pydebug
533-
suppressions_path: Tools/tsan/suppressions_free_threading.txt
534-
tsan_logs_artifact_name: tsan-logs-free-threading
535+
steps:
536+
- uses: actions/checkout@v4
537+
with:
538+
persist-credentials: false
539+
- name: Runner image version
540+
run: echo "IMAGE_VERSION=${ImageVersion}" >> "$GITHUB_ENV"
541+
- name: Restore config.cache
542+
uses: actions/cache@v4
543+
with:
544+
path: config.cache
545+
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ needs.check_source.outputs.config_hash }}
546+
- name: Register gcc problem matcher
547+
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
548+
- name: Set build dir
549+
run:
550+
# an absolute path outside of the working directoy
551+
echo "BUILD_DIR=$(realpath ${{ github.workspace }}/../build)" >> "$GITHUB_ENV"
552+
- name: Install Dependencies
553+
run: sudo ./.github/workflows/posix-deps-apt.sh
554+
- name: Configure host build
555+
run: ./configure --prefix="$BUILD_DIR/host-python"
556+
- name: Install host Python
557+
run: make -j8 install
558+
- name: Run test subset with host build
559+
run: |
560+
"$BUILD_DIR/host-python/bin/python3" -m test test_sysconfig test_site test_embed
561+
- name: Configure cross build
562+
run: ./configure --prefix="$BUILD_DIR/cross-python" --with-build-python="$BUILD_DIR/host-python/bin/python3"
563+
- name: Install cross Python
564+
run: make -j8 install
565+
- name: Run test subset with host build
566+
run: |
567+
"$BUILD_DIR/cross-python/bin/python3" -m test test_sysconfig test_site test_embed
535568
536569
# CIFuzz job based on https://google.github.io/oss-fuzz/getting-started/continuous-integration/
537570
cifuzz:
@@ -591,7 +624,6 @@ jobs:
591624
- test_hypothesis
592625
- build_asan
593626
- build_tsan
594-
- build_tsan_free_threading
595627
- cifuzz
596628

597629
runs-on: ubuntu-latest
@@ -625,7 +657,6 @@ jobs:
625657
build_windows,
626658
build_asan,
627659
build_tsan,
628-
build_tsan_free_threading,
629660
'
630661
|| ''
631662
}}

‎.github/workflows/reusable-tsan.yml

Copy file name to clipboardExpand all lines: .github/workflows/reusable-tsan.yml
+22-17Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,11 @@ on:
66
config_hash:
77
required: true
88
type: string
9-
options:
10-
required: true
11-
type: string
12-
suppressions_path:
13-
description: 'A repo relative path to the suppressions file'
14-
required: true
15-
type: string
16-
tsan_logs_artifact_name:
17-
description: 'Name of the TSAN logs artifact. Must be unique for each job.'
18-
required: true
19-
type: string
9+
free-threading:
10+
description: Whether to use free-threaded mode
11+
required: false
12+
type: boolean
13+
default: false
2014

2115
env:
2216
FORCE_COLOR: 1
@@ -26,9 +20,6 @@ jobs:
2620
name: 'Thread sanitizer'
2721
runs-on: ubuntu-24.04
2822
timeout-minutes: 60
29-
env:
30-
OPTIONS: ${{ inputs.options }}
31-
SUPPRESSIONS_PATH: ${{ inputs.suppressions_path }}
3223
steps:
3324
- uses: actions/checkout@v4
3425
with:
@@ -55,7 +46,11 @@ jobs:
5546
sudo sysctl -w vm.mmap_rnd_bits=28
5647
- name: TSAN Option Setup
5748
run: |
58-
echo "TSAN_OPTIONS=log_path=${GITHUB_WORKSPACE}/tsan_log suppressions=${GITHUB_WORKSPACE}/${SUPPRESSIONS_PATH} handle_segv=0" >> "$GITHUB_ENV"
49+
echo "TSAN_OPTIONS=log_path=${GITHUB_WORKSPACE}/tsan_log suppressions=${GITHUB_WORKSPACE}/Tools/tsan/suppressions${{
50+
fromJSON(inputs.free-threading)
51+
&& '_free_threading'
52+
|| ''
53+
}}.txt handle_segv=0" >> "$GITHUB_ENV"
5954
echo "CC=clang" >> "$GITHUB_ENV"
6055
echo "CXX=clang++" >> "$GITHUB_ENV"
6156
- name: Add ccache to PATH
@@ -67,7 +62,12 @@ jobs:
6762
save: ${{ github.event_name == 'push' }}
6863
max-size: "200M"
6964
- name: Configure CPython
70-
run: "${OPTIONS}"
65+
run: >-
66+
./configure
67+
--config-cache
68+
--with-thread-sanitizer
69+
--with-pydebug
70+
${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
7171
- name: Build CPython
7272
run: make -j4
7373
- name: Display build info
@@ -81,6 +81,11 @@ jobs:
8181
if: always()
8282
uses: actions/upload-artifact@v4
8383
with:
84-
name: ${{ inputs.tsan_logs_artifact_name }}
84+
name: >-
85+
tsan-logs-${{
86+
fromJSON(inputs.free-threading)
87+
&& 'free-threading'
88+
|| 'default'
89+
}}
8590
path: tsan_log.*
8691
if-no-files-found: ignore

‎.github/workflows/reusable-windows.yml

Copy file name to clipboardExpand all lines: .github/workflows/reusable-windows.yml
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ env:
2424
2525
jobs:
2626
build:
27-
name: 'build and test (${{ inputs.arch }})'
27+
name: ${{ inputs.arch == 'arm64' && 'build' || 'build and test' }} (${{ inputs.arch }})
2828
runs-on: ${{ inputs.os }}
2929
timeout-minutes: 60
3030
env:

‎Doc/c-api/object.rst

Copy file name to clipboardExpand all lines: Doc/c-api/object.rst
+81Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,3 +624,84 @@ Object Protocol
624624
be immortal in another.
625625
626626
.. versionadded:: next
627+
628+
.. c:function:: int PyUnstable_TryIncRef(PyObject *obj)
629+
630+
Increments the reference count of *obj* if it is not zero. Returns ``1``
631+
if the object's reference count was successfully incremented. Otherwise,
632+
this function returns ``0``.
633+
634+
:c:func:`PyUnstable_EnableTryIncRef` must have been called
635+
earlier on *obj* or this function may spuriously return ``0`` in the
636+
:term:`free threading` build.
637+
638+
This function is logically equivalent to the following C code, except that
639+
it behaves atomically in the :term:`free threading` build::
640+
641+
if (Py_REFCNT(op) > 0) {
642+
Py_INCREF(op);
643+
return 1;
644+
}
645+
return 0;
646+
647+
This is intended as a building block for managing weak references
648+
without the overhead of a Python :ref:`weak reference object <weakrefobjects>`.
649+
650+
Typically, correct use of this function requires support from *obj*'s
651+
deallocator (:c:member:`~PyTypeObject.tp_dealloc`).
652+
For example, the following sketch could be adapted to implement a
653+
"weakmap" that works like a :py:class:`~weakref.WeakValueDictionary`
654+
for a specific type:
655+
656+
.. code-block:: c
657+
658+
PyMutex mutex;
659+
660+
PyObject *
661+
add_entry(weakmap_key_type *key, PyObject *value)
662+
{
663+
PyUnstable_EnableTryIncRef(value);
664+
weakmap_type weakmap = ...;
665+
PyMutex_Lock(&mutex);
666+
weakmap_add_entry(weakmap, key, value);
667+
PyMutex_Unlock(&mutex);
668+
Py_RETURN_NONE;
669+
}
670+
671+
PyObject *
672+
get_value(weakmap_key_type *key)
673+
{
674+
weakmap_type weakmap = ...;
675+
PyMutex_Lock(&mutex);
676+
PyObject *result = weakmap_find(weakmap, key);
677+
if (PyUnstable_TryIncRef(result)) {
678+
// `result` is safe to use
679+
PyMutex_Unlock(&mutex);
680+
return result;
681+
}
682+
// if we get here, `result` is starting to be garbage-collected,
683+
// but has not been removed from the weakmap yet
684+
PyMutex_Unlock(&mutex);
685+
return NULL;
686+
}
687+
688+
// tp_dealloc function for weakmap values
689+
void
690+
value_dealloc(PyObject *value)
691+
{
692+
weakmap_type weakmap = ...;
693+
PyMutex_Lock(&mutex);
694+
weakmap_remove_value(weakmap, value);
695+
696+
...
697+
PyMutex_Unlock(&mutex);
698+
}
699+
700+
.. versionadded:: 3.14
701+
702+
.. c:function:: void PyUnstable_EnableTryIncRef(PyObject *obj)
703+
704+
Enables subsequent uses of :c:func:`PyUnstable_TryIncRef` on *obj*. The
705+
caller must hold a :term:`strong reference` to *obj* when calling this.
706+
707+
.. versionadded:: 3.14

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.