Go gRPC status.Error()在并发请求时导致无效的内存地址

huangapple go评论69阅读模式
英文:

Go gRPC status.Error() causing invalid memory address when running concurrent requests

问题

我有一个bcrypt.CompareHashAndPassword()函数,如果错误不为nil,则返回一个status.Error()给客户端。

如果我不运行并发请求,它是有效的。

如果我只是将错误返回给客户端,而不是从bcrypt返回status.Error(),那么在并发请求下一切都正常工作。我运行了测试竞争条件,没有出现任何问题。

我不确定问题是与"google.golang.org/grpc/status"库还是与"golang.org/x/crypto/bcrypt"有关。我查看了status库,我脑海中没有任何会导致此问题的地方。任何帮助都将不胜感激。

我的代码:

package main

import (
	pb "dms-cloud/authentication-microservice/pb"
	_ "github.com/go-sql-driver/mysql"
	"golang.org/x/net/context"
	"golang.org/x/crypto/bcrypt"
	"github.com/satori/go.uuid"
	"time"
	"encoding/json"
	"google.golang.org/grpc/status"
)

func (s *server) Authenticate(ctx context.Context, in *pb.AuthenticationRequest) (*pb.Ticket, error) {

	// 验证密码是否正确
	err := bcrypt.CompareHashAndPassword([]byte(in.EncryptedPassword), []byte(in.Password))
	if err != nil {
		return nil, status.Error(105, "Authentication Failed")
	}

	// 生成Ticket
	tkt := uuid.NewV4()
	exp := time.Now().Unix() + 700

	// 响应
	t := pb.Ticket{
		Uuid: tkt.String(),
		TimeExpire: exp,
		AccountId: in.AccountId,
	}

	rTkt, err := json.Marshal(t)

	err = cache.Set(tkt.String(), string(rTkt), time.Minute*60).Err()
	if err != nil {
		return nil, status.Error(500, "Internal Error")
	}

	return &t, nil
}

错误信息:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x13d96c5]

goroutine 34 [running]:
main.(*server).Authenticate(0x176f580, 0x1b44000, 0xc420194210, 0xc420192e00, 0x176f580, 0x102906e, 0x0)
        /Users/kenfab/go/src/dms-cloud/authentication-microservice/Authenticate.go:19 +0x105
dms-cloud/authentication-microservice/pb._AuthenticationMicroservice_Authenticate_Handler(0x1453060, 0x176f580, 0x1b44000, 0xc420194210, 0xc420016cd0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /Users/kenfab/go/src/dms-cloud/authentication-microservice/pb/authenticate.pb.go:240 +0x28d
google.golang.org/grpc.(*Server).processUnaryRPC(0xc4200128c0, 0x1717ec0, 0xc42001b1e0, 0xc42019c000, 0xc420019e60, 0x17464c0, 0xc4201625a0, 0x0, 0x0)
        /Users/kenfab/go/src/google.golang.org/grpc/server.go:781 +0xc41
google.golang.org/grpc.(*Server).handleStream(0xc4200128c0, 0x1717ec0, 0xc42001b1e0, 0xc42019c000, 0xc4201625a0)
        /Users/kenfab/go/src/google.golang.org/grpc/server.go:981 +0x15a6
google.golang.org/grpc.(*Server).serveStreams.func1.1(0xc420011b50, 0xc4200128c0, 0x1717ec0, 0xc42001b1e0, 0xc42019c000)
        /Users/kenfab/go/src/google.golang.org/grpc/server.go:551 +0xa9
created by google.golang.org/grpc.(*Server).serveStreams.func1
        /Users/kenfab/go/src/google.golang.org/grpc/server.go:552 +0xa1
exit status 2
英文:

I have a bcrypt.CompareHashAndPassword() function that if the error is not nil return a status.Error() back to the client.

It works If I don't run concurrent requests.

If I just return the err back to the client instead of status.Error() from the bcrypt everything works with concurrent requests. I ran it testing race conditions and nothing came up.

I'm not sure if the issue is with the "google.golang.org/grpc/status" library or with "golang.org/x/crypto/bcrypt". I looked into the status library and there are no reading/writing of maps or anything in my mind that would cause this issue. Any help appreciated.

My code:

  package main

import (
	pb "dms-cloud/authentication-microservice/pb"
	_ "github.com/go-sql-driver/mysql"
	"golang.org/x/net/context"
	"golang.org/x/crypto/bcrypt"
	"github.com/satori/go.uuid"
	"time"
	"encoding/json"
	"google.golang.org/grpc/status"
)

func (s *server) Authenticate(ctx context.Context, in *pb.AuthenticationRequest) (*pb.Ticket, error) {

	// Verify Password Correct
	err := bcrypt.CompareHashAndPassword([]byte(in.EncryptedPassword), []byte(in.Password))
	if err != nil {
		return nil, status.Error(105, "Authentication Failed")
	}

	// Generate Ticket
	tkt := uuid.NewV4()
	exp := time.Now().Unix() + 700

	// Response
	t := pb.Ticket{
		Uuid: tkt.String(),
		TimeExpire: exp,
		AccountId: in.AccountId,
	}

	rTkt, err := json.Marshal(t)

	err = cache.Set(tkt.String(), string(rTkt), time.Minute*60).Err()
	if err != nil {
		return nil, status.Error(500, "Internal Error")
	}

	return &t, nil
}

The error:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x13d96c5]

goroutine 34 [running]:
main.(*server).Authenticate(0x176f580, 0x1b44000, 0xc420194210, 0xc420192e00, 0x176f580, 0x102906e, 0x0)
        /Users/kenfab/go/src/dms-cloud/authentication-microservice/Authenticate.go:19 +0x105
dms-cloud/authentication-microservice/pb._AuthenticationMicroservice_Authenticate_Handler(0x1453060, 0x176f580, 0x1b44000, 0xc420194210, 0xc420016cd0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /Users/kenfab/go/src/dms-cloud/authentication-microservice/pb/authenticate.pb.go:240 +0x28d
google.golang.org/grpc.(*Server).processUnaryRPC(0xc4200128c0, 0x1717ec0, 0xc42001b1e0, 0xc42019c000, 0xc420019e60, 0x17464c0, 0xc4201625a0, 0x0, 0x0)
        /Users/kenfab/go/src/google.golang.org/grpc/server.go:781 +0xc41
google.golang.org/grpc.(*Server).handleStream(0xc4200128c0, 0x1717ec0, 0xc42001b1e0, 0xc42019c000, 0xc4201625a0)
        /Users/kenfab/go/src/google.golang.org/grpc/server.go:981 +0x15a6
google.golang.org/grpc.(*Server).serveStreams.func1.1(0xc420011b50, 0xc4200128c0, 0x1717ec0, 0xc42001b1e0, 0xc42019c000)
        /Users/kenfab/go/src/google.golang.org/grpc/server.go:551 +0xa9
created by google.golang.org/grpc.(*Server).serveStreams.func1
        /Users/kenfab/go/src/google.golang.org/grpc/server.go:552 +0xa1
exit status 2

答案1

得分: 1

godocs中添加的代码确实解决了这个问题。它只适用于0-15。谢谢 @jeevatkm

英文:

Added a code from godocs does solve this issue. It only works with 0 - 15. Thank You @jeevatkm

huangapple
  • 本文由 发表于 2017年8月12日 01:43:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/45640968.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定