@@ -876,16 +876,27 @@ class BytesIO(BufferedIOBase):
876876 _buffer = None
877877
878878 def __init__ (self , initial_bytes = None ):
879+ # Use to keep self._buffer and self._pos consistent.
880+ self ._lock = Lock ()
881+
879882 buf = bytearray ()
880883 if initial_bytes is not None :
881884 buf += initial_bytes
882- self ._buffer = buf
883- self ._pos = 0
885+
886+ with self ._lock :
887+ self ._buffer = buf
888+ self ._pos = 0
884889
885890 def __getstate__ (self ):
886891 if self .closed :
887892 raise ValueError ("__getstate__ on closed file" )
888- return self .__dict__ .copy ()
893+ state = self .__dict__ .copy ()
894+ del state ['_lock' ]
895+ return state
896+
897+ def __setstate__ (self , state ):
898+ self .__dict__ .update (state )
899+ self ._lock = Lock ()
889900
890901 def getvalue (self ):
891902 """Return the bytes value (contents) of the buffer
@@ -909,23 +920,25 @@ def close(self):
909920 def read (self , size = - 1 ):
910921 if self .closed :
911922 raise ValueError ("read from closed file" )
912- if size is None :
913- size = - 1
914- else :
915- try :
916- size_index = size .__index__
917- except AttributeError :
918- raise TypeError (f"{ size !r} is not an integer" )
923+
924+ with self ._lock :
925+ if size is None :
926+ size = - 1
919927 else :
920- size = size_index ()
921- if size < 0 :
922- size = len (self ._buffer )
923- if len (self ._buffer ) <= self ._pos :
924- return b""
925- newpos = min (len (self ._buffer ), self ._pos + size )
926- b = self ._buffer [self ._pos : newpos ]
927- self ._pos = newpos
928- return bytes (b )
928+ try :
929+ size_index = size .__index__
930+ except AttributeError :
931+ raise TypeError (f"{ size !r} is not an integer" )
932+ else :
933+ size = size_index ()
934+ if size < 0 :
935+ size = len (self ._buffer )
936+ if len (self ._buffer ) <= self ._pos :
937+ return b""
938+ newpos = min (len (self ._buffer ), self ._pos + size )
939+ b = self ._buffer [self ._pos : newpos ]
940+ self ._pos = newpos
941+ return bytes (b )
929942
930943 def read1 (self , size = - 1 ):
931944 """This is the same as read.
@@ -941,12 +954,14 @@ def write(self, b):
941954 n = view .nbytes # Size of any bytes-like object
942955 if n == 0 :
943956 return 0
944- pos = self ._pos
945- if pos > len (self ._buffer ):
946- # Pad buffer to pos with null bytes.
947- self ._buffer .resize (pos )
948- self ._buffer [pos :pos + n ] = b
949- self ._pos += n
957+
958+ with self ._lock :
959+ pos = self ._pos
960+ if pos > len (self ._buffer ):
961+ # Pad buffer to pos with null bytes.
962+ self ._buffer .resize (pos )
963+ self ._buffer [pos :pos + n ] = b
964+ self ._pos += n
950965 return n
951966
952967 def seek (self , pos , whence = 0 ):
@@ -978,18 +993,20 @@ def tell(self):
978993 def truncate (self , pos = None ):
979994 if self .closed :
980995 raise ValueError ("truncate on closed file" )
981- if pos is None :
982- pos = self ._pos
983- else :
984- try :
985- pos_index = pos .__index__
986- except AttributeError :
987- raise TypeError (f"{ pos !r} is not an integer" )
996+
997+ with self ._lock :
998+ if pos is None :
999+ pos = self ._pos
9881000 else :
989- pos = pos_index ()
990- if pos < 0 :
991- raise ValueError ("negative truncate position %r" % (pos ,))
992- del self ._buffer [pos :]
1001+ try :
1002+ pos_index = pos .__index__
1003+ except AttributeError :
1004+ raise TypeError (f"{ pos !r} is not an integer" )
1005+ else :
1006+ pos = pos_index ()
1007+ if pos < 0 :
1008+ raise ValueError ("negative truncate position %r" % (pos ,))
1009+ del self ._buffer [pos :]
9931010 return pos
9941011
9951012 def readable (self ):
0 commit comments