Skip to content

Commit 9817a17

Browse files
committed
Quick fix for multithreaded buffer usage.
1 parent 34df56a commit 9817a17

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

octoeverywhere/WebStream/octowebstreamhttphelper.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,9 @@ def readContentFromBodyAndMakeDataVector(
818818
defaultBodyReadSizeBytes = contentLength
819819

820820
# Some requests like snapshot requests will already have a fully read body. In this case we use the existing body buffer instead of reading from the body.
821-
# Important! This buffer must have Release() called on it because it can be holding a memory view!
821+
# Important! If the NeedsRelease flag is set we must release the buffer after we are done so the underlying buffer can be used on the next pass.
822+
# BUT not all buffers are owned by us, for example quick cam buffers, so we can't release everything.
823+
finalDataBufferNeedsReleased = False
822824
finalDataBuffer:BufferOrNone = None
823825
try:
824826
bodyReadStartSec = time.time()
@@ -850,6 +852,7 @@ def readContentFromBodyAndMakeDataVector(
850852
# NOTE this slice ALSO CREATES A MEMORY VIEW, which is then owned by the buffer, so it needs to be released.
851853
mvSlice = mv[0:readLength]
852854
finalDataBuffer = Buffer(mvSlice)
855+
finalDataBufferNeedsReleased = True
853856
else:
854857
if self.UnknownBodyChunkReadContext is not None or (responseHandlerContext is None and self.shouldDoUnknownBodyChunkRead(contentTypeLower, contentLength)):
855858
# According to the HTTP 1.1 spec, if there's no content length and no boundary string, then the body is chunk based transfer encoding.
@@ -935,10 +938,12 @@ def readContentFromBodyAndMakeDataVector(
935938
raise Exception("The builder is None, but we are trying to create a flatbuffer message.")
936939
return (originalBufferSize, len(finalDataBuffer), builder.CreateByteVector(finalDataBuffer)) #pyright: ignore[reportArgumentType, reportUnknownMemberType]
937940
finally:
938-
# If we have a data buffer, we need to make sure to call Release.
939-
# This will do nothing if it's holding bytes or a bytearray, but if it's holding a memoryview it's important that we release it
940-
# so the class body buffer can be used again.
941-
if finalDataBuffer is not None:
941+
# If we own the final data buffer, we must call release.
942+
# This is because sometimes it's a memory view, and the view needs to be released before
943+
# The underlying buffer is used in the next data read.
944+
# BUT some buffers (like those from Quick Cam or Slipstream) are shared and we CANT release them or they will break
945+
# other threaded clients using them.
946+
if finalDataBufferNeedsReleased and finalDataBuffer is not None:
942947
finalDataBuffer.Release()
943948

944949

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
# The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module
3232
# Note that this single version string is used by all of the plugins in OctoEverywhere!
33-
plugin_version = "4.3.0"
33+
plugin_version = "4.3.1"
3434

3535
# The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin
3636
# module

0 commit comments

Comments
 (0)