@@ -737,6 +737,8 @@ static PyObject *
737
737
_bufferedreader_read_generic (buffered * self , Py_ssize_t );
738
738
static Py_ssize_t
739
739
_bufferedreader_raw_read (buffered * self , char * start , Py_ssize_t len );
740
+ static int
741
+ _buffered_init (buffered * self );
740
742
741
743
/*
742
744
* Helpers
@@ -825,6 +827,60 @@ _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
825
827
return n ;
826
828
}
827
829
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
+
828
884
static int
829
885
_buffered_init (buffered * self )
830
886
{
@@ -859,6 +915,16 @@ _buffered_init(buffered *self)
859
915
self -> buffer_mask = 0 ;
860
916
if (_buffered_raw_tell (self ) == -1 )
861
917
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
+
862
928
return 0 ;
863
929
}
864
930
0 commit comments