-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
QueryContext blocks when the network is down #160
Comments
no, not quite the same. I think #91 actually describes expected behaviour, not a bug. After all, Ping() and Query() must block as long as the "pong" is yet to be seen and the TCP connection is still alive (which is usually well after the network cable is disconnected). The solution to issue #91 is "replace Ping by PingContext to avoid the halting problem", I think. But for PingContext and QueryContext it is different, I would expect for them to abort once the context is done, "no matter what". They shouldn't wait for a slow network. It is the same loop that blocks though. So this present issue (and the identical denisenkom#527) needs some unblocking. I'm a bit out of my depth. My best lead is this: readCancelConfirmation would need to (receive as a parameter and) consider the context, and stop blocking there. Maybe the connection could just be discarded and closed. Or the incoming tokens up until the cancellation confirmation would have to be consumed in the background. |
Completely untested code below. This acts on
// consume tokens until we get cancellation confirmation, or until context is done
func readCancelConfirmation(ctx context.Context, tokChan chan tokenStruct) bool {
for {
select {
case <-ctx.Done():
// this should in effect discard the connection. Debatable.
return false
case tok, alive := <-tokChan:
if !alive {
// tokChan is closed.
return false
}
confirmToken, isConfirmation := tok.(*doneStruct)
if isConfirmation && (confirmToken.Status&doneAttn != 0) {
// got cancellation confirmation, the connection is usable again
return true
}
}
}
} Actually it is debatable if |
Is there any update on this issue? Is there a current workaround, like moving all queries into goroutines? That's a bit tedious and I'm unsure if doing so would mean we get memory leaks. |
I'm afraid we should cast to confirmToken, isConfirmation := tok.(doneStruct) This is because the original function is: func readCancelConfirmation(tokChan chan tokenStruct) bool {
for tok := range tokChan {
switch tok := tok.(type) {
default:
// just skip token
case doneStruct: // the struct type, not the pointer to it
if tok.Status&doneAttn != 0 {
// got cancellation confirmation, exit
return true
}
}
}
return false
} |
QueryContext blocks when the network is down
I want to deal with sometimes slow or unreliable network connections, and use QueryContext to limit query time.
After a connection is established (by Ping() or previous queries), and then fails (in my experiments I disconnect the VPN connection to the server), the next QueryContext hangs indefinitely even after the context is cancelled.
To reproduce, see https://github.com/tiwo/2023-gomssqldb-issue-with-timeout
Tested with Go 1.21.3, go-mssqldb 1.6.0.
For what it's worth, I am setting db.SetConnMaxLifetime which should be unrelated, and I am making sure the context really is cancelled.
Is the context even used in Stmt.sendQuery, except for logging?
The text was updated successfully, but these errors were encountered: