@@ -140,10 +140,14 @@ pub(crate) fn infer_to_python_known(
140140 . into_py_any ( py) ?,
141141 ObType :: Bytearray => {
142142 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+ } ) ?
147151 }
148152 ObType :: Tuple => {
149153 let elements = serialize_seq_filter ! ( PyTuple ) ;
@@ -432,12 +436,14 @@ pub(crate) fn infer_serialize_known<S: Serializer>(
432436 }
433437 ObType :: Bytearray => {
434438 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+ } )
441447 }
442448 ObType :: Dict => {
443449 let dict = value. downcast :: < PyDict > ( ) . map_err ( py_err_se_err) ?;
@@ -612,15 +618,15 @@ pub(crate) fn infer_json_key_known<'a>(
612618 . bytes_to_string ( key. py ( ) , key. downcast :: < PyBytes > ( ) ?. as_bytes ( ) ) ,
613619 ObType :: Bytearray => {
614620 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 ( ) ) )
624630 }
625631 ObType :: Datetime => {
626632 let iso_dt = super :: type_serializers:: datetime_etc:: datetime_to_string ( key. downcast ( ) ?) ?;
0 commit comments