etcdserver: fix a node panic bug caused LeaseTimeToLive call on a nonexistent lease

When the non Leader etcd server receives a LeaseTimeToLive on a nonexistent lease, it responds with a nil resp and a nil error The invoking function parses the nil resp and results a segmentation fault.
I fix the bug by making sure the lease not found error is returned so that the invoking function parses the the error message instead.

fix #6537
This commit is contained in:
fanmin shi 2016-09-27 15:32:06 -07:00
parent e68cd086ee
commit 8ef6687018
2 changed files with 27 additions and 5 deletions

View File

@ -308,17 +308,15 @@ func (s *EtcdServer) LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveR
return nil, err return nil, err
} }
var lresp *pb.LeaseTimeToLiveResponse
for _, url := range leader.PeerURLs { for _, url := range leader.PeerURLs {
lurl := url + leasehttp.LeaseInternalPrefix lurl := url + leasehttp.LeaseInternalPrefix
var iresp *leasepb.LeaseInternalResponse var iresp *leasepb.LeaseInternalResponse
iresp, err = leasehttp.TimeToLiveHTTP(ctx, lease.LeaseID(r.ID), r.Keys, lurl, s.peerRt) iresp, err = leasehttp.TimeToLiveHTTP(ctx, lease.LeaseID(r.ID), r.Keys, lurl, s.peerRt)
if err == nil { if err == nil {
lresp = iresp.LeaseTimeToLiveResponse return iresp.LeaseTimeToLiveResponse, nil
break
} }
} }
return lresp, nil return nil, err
} }
func (s *EtcdServer) waitLeader() (*membership.Member, error) { func (s *EtcdServer) waitLeader() (*membership.Member, error) {

View File

@ -243,7 +243,31 @@ func TestV3PutOnNonExistLease(t *testing.T) {
putr := &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: badLeaseID} putr := &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: badLeaseID}
_, err := toGRPC(clus.RandClient()).KV.Put(ctx, putr) _, err := toGRPC(clus.RandClient()).KV.Put(ctx, putr)
if !eqErrGRPC(err, rpctypes.ErrGRPCLeaseNotFound) { if !eqErrGRPC(err, rpctypes.ErrGRPCLeaseNotFound) {
t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCCompacted) t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCLeaseNotFound)
}
}
// TestV3GetNonExistLease tests the case where the non exist lease is report as lease not found error using LeaseTimeToLive()
// A bug was found when a non leader etcd server returns nil instead of lease not found error which caues the server to crash.
// related issue https://github.com/coreos/etcd/issues/6537
func TestV3GetNonExistLease(t *testing.T) {
defer testutil.AfterTest(t)
clus := NewClusterV3(t, &ClusterConfig{Size: 3})
defer clus.Terminate(t)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
leaseTTLr := &pb.LeaseTimeToLiveRequest{
ID: 123,
Keys: true,
}
for _, client := range clus.clients {
_, err := toGRPC(client).Lease.LeaseTimeToLive(ctx, leaseTTLr)
if !eqErrGRPC(err, rpctypes.ErrGRPCLeaseNotFound) {
t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCLeaseNotFound)
}
} }
} }