@@ -737,6 +737,8 @@ static PyObject *
737737_bufferedreader_read_generic (buffered * self , Py_ssize_t );
738738static Py_ssize_t
739739_bufferedreader_raw_read (buffered * self , char * start , Py_ssize_t len );
740+ static int
741+ _buffered_init (buffered * self );
740742
741743/*
742744 * Helpers
@@ -825,6 +827,60 @@ _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
825827 return n ;
826828}
827829
830+ #ifdef HAVE_FORK
831+
832+ static PyObject *
833+ buffered_after_fork_child_impl (PyObject * self , PyObject * Py_UNUSED (ignored ))
834+ {
835+ buffered * buf = (buffered * )self ;
836+ if (_buffered_init (buf ) < 0 ) {
837+ PyErr_SetString (PyExc_RuntimeError , "Failed to initialize buffer after fork" );
838+ return NULL ;
839+ }
840+ _bufferedreader_reset_buf (buf );
841+ Py_RETURN_NONE ;
842+ }
843+
844+ static PyMethodDef buffered_fork_methods [] = {
845+ {"_after_fork_child" , buffered_after_fork_child_impl , METH_NOARGS , NULL },
846+ {NULL , NULL }
847+ };
848+
849+ static int
850+ buffered_register_at_fork (buffered * self )
851+ {
852+ PyInterpreterState * interp = PyThreadState_Get ()-> interp ;
853+ if (!interp ) {
854+ PyErr_SetString (PyExc_RuntimeError , "Failed to get interpreter state" );
855+ return -1 ;
856+ }
857+
858+ // Only register the fork handlers once
859+ if (!interp -> after_forkers_child ) {
860+ interp -> after_forkers_child = PyList_New (0 );
861+ if (!interp -> after_forkers_child ) {
862+ return -1 ;
863+ }
864+ }
865+
866+ /* Create method objects */
867+ PyObject * after_child = PyCFunction_New (& buffered_fork_methods [0 ], (PyObject * )self );
868+ if (!after_child ) {
869+ return -1 ;
870+ }
871+
872+ /* Append callbacks to the lists */
873+ int status = 0 ;
874+ if (PyList_Append (interp -> after_forkers_child , after_child ) < 0 ) {
875+ status = -1 ;
876+ }
877+
878+ Py_DECREF (after_child );
879+ return status ;
880+ }
881+
882+ #endif /* HAVE_FORK */
883+
828884static int
829885_buffered_init (buffered * self )
830886{
@@ -859,6 +915,16 @@ _buffered_init(buffered *self)
859915 self -> buffer_mask = 0 ;
860916 if (_buffered_raw_tell (self ) == -1 )
861917 PyErr_Clear ();
918+
919+ #ifdef HAVE_FORK
920+ /* Register fork handlers */
921+ if (buffered_register_at_fork (self ) < 0 ) {
922+ PyThread_free_lock (self -> lock );
923+ self -> lock = NULL ;
924+ return -1 ;
925+ }
926+ #endif /* HAVE_FORK */
927+
862928 return 0 ;
863929}
864930
0 commit comments