You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If the redis server is quite busy or taking a lot of time to respond to requests it may not push all data across the socket in one go. When this happens the singular command append readBuf [read $sock] in the readEvent proc can result in a partial read of the server's response and cause truncated data to be passed to ParseBuf. Below is an excerpt of the error that this behaviour causes:
Could not set respType: Invalid type byte:
while executing
"{*}$errorCallback $msg"
(class "::retcl" method "Error" line 2)
invoked from within
"my Error "Could not set respType: $error $startIdx""
(class "::retcl" method "ParseBuf" line 11)
invoked from within
"my ParseBuf $buffer $idx"
(class "::retcl" method "ParseBuf" line 81)
invoked from within
"my ParseBuf $buffer $idx"
(class "::retcl" method "ParseBuf" line 81)
invoked from within
"my ParseBuf $readBuf $idx"
(class "::retcl" method "readEvent" line 12)
invoked from within
"::oo::Obj18 readEvent"
The solution here seems to be to allow the latter proc to make another call to [read $sock] if the buffer length is equal to or less than the expected index up to which the buffer has been parsed. I am not sure if this fix causes a potential problem asynchronous requests (it might) but I am largely using synchronous mode in an otherwise threaded program.
Below is a patch that fixes the problem of truncated buffers.
Index: tcltk/retcl.git/retcl.tm
==================================================================
--- tcltk/retcl.git/retcl.tm
+++ tcltk/retcl.git/retcl.tm
@@ -524,11 +524,11 @@
append readBuf [read $sock]
set idx 0
while {$idx < [string length $readBuf]} {
- set result [my ParseBuf $readBuf $idx]
+ set result [my ParseBuf $idx]
if {$result eq {}} {
break
}
lassign $result idx type data
@@ -547,27 +547,32 @@
# idx : index up to which the buffer has been parsed
# type : type of the object found
# value : value of the object
#
# or the empty string if no complete object could be parsed.
- method ParseBuf {buffer startIdx} {
+ method ParseBuf {startIdx} {
+ set readBufLength [string length $readBuf]
- if {![string length $buffer]} {
+ if {!$readBufLength} {
return
}
- set respCode [string index $buffer $startIdx]
+ if {$readBufLength <= $startIdx} {
+ append readBuf [read $sock]
+ }
+
+ set respCode [string index $readBuf $startIdx]
set respType [my TypeName $respCode]
switch -- $respCode {
"+" -
"-" -
":" {
# Simple Strings, Errors, and Integers are handled
# straight forward
- lassign [my ParseLine $buffer $startIdx+1] eol line
+ lassign [my ParseLine $readBuf $startIdx+1] eol line
if {$eol == -1} {
return
}
return [list [expr {$eol+2}] $respType $line]
}
@@ -574,11 +579,11 @@
"$" {
# Bulk Strings, the number of characters is specified in the
# first line. We handle Null values and empty strings right
# away.
- lassign [my ParseLine $buffer $startIdx+1] eol bulkLen
+ lassign [my ParseLine $readBuf $startIdx+1] eol bulkLen
if {$eol == -1} {
return
}
# Null Bulk String
@@ -592,21 +597,21 @@
}
# Non-empty Bulk String
incr eol 2
set endIdx [expr {$eol+$bulkLen-1}]
- if {[string length $buffer] < [expr {$endIdx+2}]} {
+ if {[string length $readBuf] < [expr {$endIdx+2}]} {
# Need to wait for more input
return
}
- return [list [expr {$endIdx+3}] $respType [string range $buffer $eol $endIdx]]
+ return [list [expr {$endIdx+3}] $respType [string range $readBuf $eol $endIdx]]
}
"*" {
# Arrays, the number of elements is specified in the first
# line.
- lassign [my ParseLine $buffer $startIdx+1] eol arrLen
+ lassign [my ParseLine $readBuf $startIdx+1] eol arrLen
if {$eol == -1} {
return
}
# Null Array
@@ -620,12 +625,13 @@
}
# Non-empty Array
set idx [expr {$eol+2}]
set elems [list]
+
while {$arrLen} {
- set elem [my ParseBuf $buffer $idx]
+ set elem [my ParseBuf $idx]
if {$elem eq {}} {
return {}
}
lappend elems [lindex $elem 2]
@@ -635,11 +641,11 @@
return [list $idx $respType $elems]
}
default {
- puts "Unhandled type: $buffer"
+ puts "Unhandled type: $readBuf"
}
}
}
method ParseLine {buffer startIdx} {
The text was updated successfully, but these errors were encountered:
Hi @mattadams, thanks for the report! I designed ParseBuf to return with an empty value in case of an incomplete read, so the next readEvent has a chance to append another bunch of bytes to readBuf and try again. Obviously, this isn't working in your case. It is not clear to me why, yet. Also, it's been a while since I worked on this codebase, so it'll take me some time to familiarize myself with it again :) Do you have a chance to provide the contents of the partial read in your use case?
If the redis server is quite busy or taking a lot of time to respond to requests it may not push all data across the socket in one go. When this happens the singular command
append readBuf [read $sock]
in thereadEvent
proc can result in a partial read of the server's response and cause truncated data to be passed toParseBuf
. Below is an excerpt of the error that this behaviour causes:The solution here seems to be to allow the latter proc to make another call to
[read $sock]
if the buffer length is equal to or less than the expected index up to which the buffer has been parsed. I am not sure if this fix causes a potential problem asynchronous requests (it might) but I am largely using synchronous mode in an otherwise threaded program.Below is a patch that fixes the problem of truncated buffers.
The text was updated successfully, but these errors were encountered: