@@ -140,10 +140,14 @@ pub(crate) fn infer_to_python_known(
140
140
. into_py_any ( py) ?,
141
141
ObType :: Bytearray => {
142
142
let py_byte_array = value. downcast :: < PyByteArray > ( ) ?;
143
- // Safety: the GIL is held while bytes_to_string is running; it doesn't run
144
- // arbitrary Python code, so py_byte_array cannot be mutated.
145
- let bytes = unsafe { py_byte_array. as_bytes ( ) } ;
146
- extra. config . bytes_mode . bytes_to_string ( py, bytes) ?. into_py_any ( py) ?
143
+ pyo3:: sync:: with_critical_section ( py_byte_array, || {
144
+ // SAFETY: `py_byte_array` is protected by a critical section,
145
+ // which guarantees no mutation, and `bytes_to_string` does not
146
+ // run any code which could cause the critical section to be
147
+ // released.
148
+ let bytes = unsafe { py_byte_array. as_bytes ( ) } ;
149
+ extra. config . bytes_mode . bytes_to_string ( py, bytes) ?. into_py_any ( py)
150
+ } ) ?
147
151
}
148
152
ObType :: Tuple => {
149
153
let elements = serialize_seq_filter ! ( PyTuple ) ;
@@ -432,12 +436,14 @@ pub(crate) fn infer_serialize_known<S: Serializer>(
432
436
}
433
437
ObType :: Bytearray => {
434
438
let py_byte_array = value. downcast :: < PyByteArray > ( ) . map_err ( py_err_se_err) ?;
435
- // Safety: the GIL is held while serialize_bytes is running; it doesn't run
436
- // arbitrary Python code, so py_byte_array cannot be mutated.
437
- extra
438
- . config
439
- . bytes_mode
440
- . serialize_bytes ( unsafe { py_byte_array. as_bytes ( ) } , serializer)
439
+ pyo3:: sync:: with_critical_section ( py_byte_array, || {
440
+ // SAFETY: `py_byte_array` is protected by a critical section,
441
+ // which guarantees no mutation, and `serialize_bytes` does not
442
+ // run any code which could cause the critical section to be
443
+ // released.
444
+ let bytes = unsafe { py_byte_array. as_bytes ( ) } ;
445
+ extra. config . bytes_mode . serialize_bytes ( bytes, serializer)
446
+ } )
441
447
}
442
448
ObType :: Dict => {
443
449
let dict = value. downcast :: < PyDict > ( ) . map_err ( py_err_se_err) ?;
@@ -612,15 +618,15 @@ pub(crate) fn infer_json_key_known<'a>(
612
618
. bytes_to_string ( key. py ( ) , key. downcast :: < PyBytes > ( ) ?. as_bytes ( ) ) ,
613
619
ObType :: Bytearray => {
614
620
let py_byte_array = key. downcast :: < PyByteArray > ( ) ?;
615
- // Safety: the GIL is held while serialize_bytes is running; it doesn't run
616
- // arbitrary Python code, so py_byte_array cannot be mutated during the call.
617
- //
618
- // We copy the bytes into a new buffer immediately afterwards
619
- extra
620
- . config
621
- . bytes_mode
622
- . bytes_to_string ( key . py ( ) , unsafe { py_byte_array . as_bytes ( ) } )
623
- . map ( |cow| Cow :: Owned ( cow. into_owned ( ) ) )
621
+ pyo3 :: sync :: with_critical_section ( py_byte_array , || {
622
+ // SAFETY: ` py_byte_array` is protected by a critical section,
623
+ // which guarantees no mutation, and `bytes_to_string` does not
624
+ // run any code which could cause the critical section to be
625
+ // released.
626
+ let bytes = unsafe { py_byte_array . as_bytes ( ) } ;
627
+ extra . config . bytes_mode . bytes_to_string ( key . py ( ) , bytes )
628
+ } )
629
+ . map ( |cow| Cow :: Owned ( cow. into_owned ( ) ) )
624
630
}
625
631
ObType :: Datetime => {
626
632
let iso_dt = super :: type_serializers:: datetime_etc:: datetime_to_string ( key. downcast ( ) ?) ?;
0 commit comments