-
Notifications
You must be signed in to change notification settings - Fork 54
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
Fix race in idle expiration #47
Conversation
for _, stream := range streams { | ||
stream.resetStream() | ||
} | ||
}() | ||
i.conn.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it safer to have this inside the goroutine too? It sends a goaway frame, which means it's sending to resetChan
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you happen to set resetChan's capacity to 0, this hangs unless you move i.conn.Close() inside the goroutine - it's probably safest that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggesting i.conn.Close is inside the goroutine before the resets? I don't like that hanging is a possibility on Close but I see it is only because the resetChan cannot be read from while this call is done. I will make that update, my main concern was i.conn.streams was updated before Close.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inside the goroutine after the resets, if that works for you?
On Fri, Feb 27, 2015 at 7:12 PM Derek McGowan notifications@github.com
wrote:
In connection.go
#47 (comment):@@ -72,11 +72,17 @@ Loop:
timer.Reset(i.timeout)
}
case <-expired:
for _, stream := range i.conn.streams {
stream.Reset()
}
i.conn.streamCond.L.Lock()
streams := i.conn.streams
i.conn.streams = make(map[spdy.StreamId]*Stream)
i.conn.streamCond.Broadcast()
i.conn.streamCond.L.Unlock()
go func() {
for _, stream := range streams {
stream.resetStream()
}
}() i.conn.Close()
Suggesting i.conn.Close is inside the goroutine before the resets? I don't
like that hanging is a possibility on Close but I see it is only because
the resetChan cannot be read from while this call is done. I will make that
update, my main concern was i.conn.streams was updated before Close.—
Reply to this email directly or view it on GitHub
https://github.com/docker/spdystream/pull/47/files#r25549366.
On expiration reset is called, causing a race between resetting objects and accessing the streams. Additionally a deadlock occurs writing frames which can be avoided by running the actual sending of the resets in a goroutine. Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
65fc6cb
to
1fdaf41
Compare
LGTM Also looks like we still need #46 for OS X. This one unfortunately doesn't fix that issue. |
On expiration reset is called, causing a race between resetting objects and accessing the streams. Additionally a deadlock occurs writing frames which can be avoided by running the actual sending of the resets in a goroutine.