@@ -731,6 +731,8 @@ static PyObject *
731731_bufferedreader_read_generic (buffered * self , Py_ssize_t );
732732static Py_ssize_t
733733_bufferedreader_raw_read (buffered * self , char * start , Py_ssize_t len );
734+ static int
735+ _buffered_init (buffered * self );
734736
735737/*
736738 * Helpers
@@ -819,6 +821,60 @@ _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
819821 return n ;
820822}
821823
824+ #ifdef HAVE_FORK
825+
826+ static PyObject *
827+ buffered_after_fork_child_impl (PyObject * self , PyObject * Py_UNUSED (ignored ))
828+ {
829+ buffered * buf = (buffered * )self ;
830+ if (_buffered_init (buf ) < 0 ) {
831+ PyErr_SetString (PyExc_RuntimeError , "Failed to initialize buffer after fork" );
832+ return NULL ;
833+ }
834+ _bufferedreader_reset_buf (buf );
835+ Py_RETURN_NONE ;
836+ }
837+
838+ static PyMethodDef buffered_fork_methods [] = {
839+ {"_after_fork_child" , buffered_after_fork_child_impl , METH_NOARGS , NULL },
840+ {NULL , NULL }
841+ };
842+
843+ static int
844+ buffered_register_at_fork (buffered * self )
845+ {
846+ PyInterpreterState * interp = PyThreadState_Get ()-> interp ;
847+ if (!interp ) {
848+ PyErr_SetString (PyExc_RuntimeError , "Failed to get interpreter state" );
849+ return -1 ;
850+ }
851+
852+ // Only register the fork handlers once
853+ if (!interp -> after_forkers_child ) {
854+ interp -> after_forkers_child = PyList_New (0 );
855+ if (!interp -> after_forkers_child ) {
856+ return -1 ;
857+ }
858+ }
859+
860+ /* Create method objects */
861+ PyObject * after_child = PyCFunction_New (& buffered_fork_methods [0 ], (PyObject * )self );
862+ if (!after_child ) {
863+ return -1 ;
864+ }
865+
866+ /* Append callbacks to the lists */
867+ int status = 0 ;
868+ if (PyList_Append (interp -> after_forkers_child , after_child ) < 0 ) {
869+ status = -1 ;
870+ }
871+
872+ Py_DECREF (after_child );
873+ return status ;
874+ }
875+
876+ #endif /* HAVE_FORK */
877+
822878static int
823879_buffered_init (buffered * self )
824880{
@@ -853,6 +909,16 @@ _buffered_init(buffered *self)
853909 self -> buffer_mask = 0 ;
854910 if (_buffered_raw_tell (self ) == -1 )
855911 PyErr_Clear ();
912+
913+ #ifdef HAVE_FORK
914+ /* Register fork handlers */
915+ if (buffered_register_at_fork (self ) < 0 ) {
916+ PyThread_free_lock (self -> lock );
917+ self -> lock = NULL ;
918+ return -1 ;
919+ }
920+ #endif /* HAVE_FORK */
921+
856922 return 0 ;
857923}
858924
0 commit comments