Skip to content

Commit 4c1e940

Browse files
committed
Replace critical sections with atomic operations
1 parent 81a459c commit 4c1e940

File tree

3 files changed

+19
-14
lines changed

3 files changed

+19
-14
lines changed

Include/internal/pycore_pyatomic_ft_wrappers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ extern "C" {
7777
_Py_atomic_store_ushort_relaxed(&value, new_value)
7878
#define FT_ATOMIC_LOAD_USHORT_RELAXED(value) \
7979
_Py_atomic_load_ushort_relaxed(&value)
80+
#define FT_ATOMIC_LOAD_INT(value) \
81+
_Py_atomic_load_int(&value)
82+
#define FT_ATOMIC_STORE_INT(value, new_value) \
83+
_Py_atomic_store_int(&value, new_value)
8084
#define FT_ATOMIC_STORE_INT_RELAXED(value, new_value) \
8185
_Py_atomic_store_int_relaxed(&value, new_value)
8286
#define FT_ATOMIC_LOAD_INT_RELAXED(value) \
@@ -144,6 +148,8 @@ extern "C" {
144148
#define FT_ATOMIC_STORE_SHORT_RELAXED(value, new_value) value = new_value
145149
#define FT_ATOMIC_LOAD_USHORT_RELAXED(value) value
146150
#define FT_ATOMIC_STORE_USHORT_RELAXED(value, new_value) value = new_value
151+
#define FT_ATOMIC_LOAD_INT(value) value
152+
#define FT_ATOMIC_STORE_INT(value, new_value) value = new_value
147153
#define FT_ATOMIC_LOAD_INT_RELAXED(value) value
148154
#define FT_ATOMIC_STORE_INT_RELAXED(value, new_value) value = new_value
149155
#define FT_ATOMIC_LOAD_UINT_RELAXED(value) value
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix thread safety issue with :mod:`re` scanner objects in free-threaded
2+
builds.

Modules/_sre/sre.c

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2841,28 +2841,25 @@ scanner_dealloc(PyObject *self)
28412841
static int
28422842
scanner_begin(ScannerObject* self)
28432843
{
2844-
int result;
2845-
Py_BEGIN_CRITICAL_SECTION(self);
2846-
if (self->executing) {
2844+
#ifdef Py_GIL_DISABLED
2845+
int was_executing = _Py_atomic_exchange_int(&self->executing, 1);
2846+
#else
2847+
int was_executing = self->executing;
2848+
self->executing = 1;
2849+
#endif
2850+
if (was_executing) {
28472851
PyErr_SetString(PyExc_ValueError,
28482852
"regular expression scanner already executing");
2849-
result = 0;
2850-
}
2851-
else {
2852-
self->executing = 1;
2853-
result = 1;
2853+
return 0;
28542854
}
2855-
Py_END_CRITICAL_SECTION();
2856-
return result;
2855+
return 1;
28572856
}
28582857

28592858
static void
28602859
scanner_end(ScannerObject* self)
28612860
{
2862-
Py_BEGIN_CRITICAL_SECTION(self);
2863-
assert(self->executing);
2864-
self->executing = 0;
2865-
Py_END_CRITICAL_SECTION();
2861+
assert(FT_ATOMIC_LOAD_INT_RELAXED(self->executing));
2862+
FT_ATOMIC_STORE_INT(self->executing, 0);
28662863
}
28672864

28682865
/*[clinic input]

0 commit comments

Comments
 (0)