-
Notifications
You must be signed in to change notification settings - Fork 84
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
Add a way to signal when a Channel has closed #718
Conversation
testutils/test_server.go
Outdated
@@ -294,6 +294,9 @@ func (ts *TestServer) addChannel(createChannel func(t testing.TB, opts *ChannelO | |||
func (ts *TestServer) close(ch *tchannel.Channel) { | |||
ch.Close() | |||
ts.waitForChannelClose(ch) |
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.
can we replace the waitForChannelClose
with a select statement on the channel instead? The select
should have a timeout as well.
we should remove all existing loops where we wait for close with the channel instead
803db35
to
16633c9
Compare
Codecov Report
@@ Coverage Diff @@
## dev #718 +/- ##
==========================================
+ Coverage 86.92% 87.73% +0.81%
==========================================
Files 40 40
Lines 4060 4068 +8
==========================================
+ Hits 3529 3569 +40
+ Misses 407 377 -30
+ Partials 124 122 -2
Continue to review full report at Codecov.
|
channel.go
Outdated
|
||
ch.mutable.Lock() | ||
select { | ||
case <-ch.mutable.closed: |
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.
Do we need this check, I think onClosed
is guaranteed to only happen once right?
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.
I thought so too, but it looks like it's called from both Close
and connectionCloseStateChange
.
And the tests appear to fail if I don't guard it.
channel.go
Outdated
@@ -281,6 +282,7 @@ func NewChannel(serviceName string, opts *ChannelOptions) (*Channel, error) { | |||
} | |||
ch.mutable.state = ChannelClient | |||
ch.mutable.conns = make(map[uint32]*Connection) | |||
ch.mutable.closed = make(chan struct{}) |
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.
why is closed
mutable? I think it's immutable (set on channel creation) and should only ever be closed once
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.
Makes sense. Moved it out of mutable
.
channel.go
Outdated
@@ -758,6 +760,16 @@ func (ch *Channel) connectionCloseStateChange(c *Connection) { | |||
|
|||
func (ch *Channel) onClosed() { | |||
removeClosedChannel(ch) | |||
|
|||
ch.mutable.Lock() |
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.
see above, don't think this is mutable or needs a lock
testutils/test_server.go
Outdated
ts.waitForChannelClose(ch) | ||
|
||
select { | ||
case <-time.After(500 * time.Millisecond): |
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.
- use
testutils.Timeout
-- the value should be scaled up in slwoer environments. - The previous code did 60 iterations, each iteration taking i * 100 microseconds. i think this means we waited 100 microseconds * (1 + 2 + 3 + ... 60). That ends up being roughly 1800 * 100 microseconds or 180ms. This is a slight bump up (probably needed because we weren't using
testutils.Timeout
. I'm OK with keeping this higher, but can we test if 200ms works OK?
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.
I tried this with 250ms and it was still failing, https://travis-ci.org/uber/tchannel-go/builds/436414905.
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.
Errrp.. looks like I missed
export TEST_TIMEOUT_SCALE=20
Sounds like 200ms should work and then the Travis scaling should let it work.
testutils/test_server.go
Outdated
|
||
select { | ||
case <-time.After(500 * time.Millisecond): | ||
ts.Errorf("Channel %p did not close after 500 ms, last state: %v", ch, ch.State()) |
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.
once we use Timeout(500ms)
, we might want to use the same value here
1ac7f7a
to
86f0a2b
Compare
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.
Looks pretty good, just one comment on the onClosed
logic
channel.go
Outdated
|
||
select { | ||
case <-ch.closed: | ||
// Do nothing if already closed. |
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.
Why would it already be closed? Only if we have a bug right? We can either:
- always close (which would panic in prod if we closed an already closed channel). since channels aren't created dynamically anyway, this seems OK
- log an error if the channel's already closed
channel.go
Outdated
@@ -266,6 +267,8 @@ func NewChannel(serviceName string, opts *ChannelOptions) (*Channel, error) { | |||
ch.handler = channelHandler{ch} | |||
} | |||
|
|||
ch.closed = make(chan struct{}) |
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.
can you add this field to the channel constructor,
closed: make(chan struct{}),
af53943
to
df7e7b4
Compare
Channel has Close() and Closed() methods that tells a Channel to close and returns whether the Channel is already closed, respectively. This adds a CloseChan() that returns a channel that will close once the Channel has completed closing.
df7e7b4
to
10bdac1
Compare
Channel has Close() and Closed() methods that tells a Channel to close
and returns whether the Channel is already closed, respectively. This
adds a CloseChan() that returns a channel that will close once the
Channel has completed closing.