Skip to content
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

Ensure GRPCServer.Stop() calls GRPCBroker.Close() #220

Merged
merged 3 commits into from Nov 8, 2022

Conversation

bflad
Copy link
Member

@bflad bflad commented Nov 4, 2022

Initializing a GRPCServer will do the following:

	// Register the broker service
	brokerServer := newGRPCBrokerServer()
	plugin.RegisterGRPCBrokerServer(s.server, brokerServer)
	s.broker = newGRPCBroker(brokerServer, s.TLS)
	go s.broker.Run()

The current Stop() method omits any handling of the underlying s.broker, which means the broker goroutine will leak:

        [Goroutine 53 in state select, with github.com/hashicorp/go-plugin.(*gRPCBrokerServer).Recv on top of the stack:
        goroutine 53 [select]:
        github.com/hashicorp/go-plugin.(*gRPCBrokerServer).Recv(0x29?)
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_broker.go:121 +0x58
        github.com/hashicorp/go-plugin.(*GRPCBroker).Run(0x140003ca190)
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_broker.go:411 +0x40
        created by github.com/hashicorp/go-plugin.(*GRPCServer).Init
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_server.go:85 +0x424
        ]

If there is another/better way to handle these, please reach out.

Initializing a GRPCServer will do the following:

```go
	// Register the broker service
	brokerServer := newGRPCBrokerServer()
	plugin.RegisterGRPCBrokerServer(s.server, brokerServer)
	s.broker = newGRPCBroker(brokerServer, s.TLS)
	go s.broker.Run()
```

The current Stop() method omits any handling of the underlying `s.broker`, which means the broker goroutine will leak:

```text
        [Goroutine 53 in state select, with github.com/hashicorp/go-plugin.(*gRPCBrokerServer).Recv on top of the stack:
        goroutine 53 [select]:
        github.com/hashicorp/go-plugin.(*gRPCBrokerServer).Recv(0x29?)
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_broker.go:121 +0x58
        github.com/hashicorp/go-plugin.(*GRPCBroker).Run(0x140003ca190)
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_broker.go:411 +0x40
        created by github.com/hashicorp/go-plugin.(*GRPCServer).Init
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_server.go:85 +0x424
        ]
```
@bflad bflad added the bug label Nov 4, 2022
bflad added a commit to hashicorp/terraform-plugin-sdk that referenced this pull request Nov 4, 2022
Reference: #1063
Reference: hashicorp/go-plugin#220

This includes the following small bug fixes:

- Clarifies/fixes the trace logging during `terraform show` commands
- Improves performance slightly for `terraform show` raw plan usage (terraform-exec already captures and returns stdout for raw plans)
- Prevents a goroutine leak specific to the detached stop context in `schema.GRPCProvider`

Previously, leak detection on testing would contain an entry per Terraform command such as:

```
        [Goroutine 276 in state select, with github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.mergeStop on top of the stack:
        goroutine 276 [select]:
        github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.mergeStop({0x103a5f298?, 0x14000390c00?}, 0x1400033e5f0, 0x140004bb560)
                /Users/bflad/src/github.com/hashicorp/terraform-plugin-sdk/helper/schema/grpc_provider.go:46 +0x64
        created by github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).StopContext
                /Users/bflad/src/github.com/hashicorp/terraform-plugin-sdk/helper/schema/grpc_provider.go:63 +0x178
        ]
```

Leaked goroutines such as:

```
        [Goroutine 53 in state select, with github.com/hashicorp/go-plugin.(*gRPCBrokerServer).Recv on top of the stack:
        goroutine 53 [select]:
        github.com/hashicorp/go-plugin.(*gRPCBrokerServer).Recv(0x29?)
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_broker.go:121 +0x58
        github.com/hashicorp/go-plugin.(*GRPCBroker).Run(0x140003ca190)
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_broker.go:411 +0x40
        created by github.com/hashicorp/go-plugin.(*GRPCServer).Init
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_server.go:85 +0x424
        ]
```

Will likely require a fix upstream in go-plugin.
bflad added a commit to hashicorp/terraform-plugin-sdk that referenced this pull request Nov 7, 2022
Reference: #1063
Reference: hashicorp/go-plugin#220

This includes the following small bug fixes:

- Clarifies/fixes the trace logging during `terraform show` commands
- Improves performance slightly for `terraform show` raw plan usage (terraform-exec already captures and returns stdout for raw plans)
- Prevents a goroutine leak specific to the detached stop context in `schema.GRPCProvider`

Previously, leak detection on testing would contain an entry per Terraform command such as:

```
        [Goroutine 276 in state select, with github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.mergeStop on top of the stack:
        goroutine 276 [select]:
        github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.mergeStop({0x103a5f298?, 0x14000390c00?}, 0x1400033e5f0, 0x140004bb560)
                /Users/bflad/src/github.com/hashicorp/terraform-plugin-sdk/helper/schema/grpc_provider.go:46 +0x64
        created by github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).StopContext
                /Users/bflad/src/github.com/hashicorp/terraform-plugin-sdk/helper/schema/grpc_provider.go:63 +0x178
        ]
```

Leaked goroutines such as:

```
        [Goroutine 53 in state select, with github.com/hashicorp/go-plugin.(*gRPCBrokerServer).Recv on top of the stack:
        goroutine 53 [select]:
        github.com/hashicorp/go-plugin.(*gRPCBrokerServer).Recv(0x29?)
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_broker.go:121 +0x58
        github.com/hashicorp/go-plugin.(*GRPCBroker).Run(0x140003ca190)
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_broker.go:411 +0x40
        created by github.com/hashicorp/go-plugin.(*GRPCServer).Init
                /Users/bflad/go/pkg/mod/github.com/hashicorp/go-plugin@v1.4.4/grpc_server.go:85 +0x424
        ]
```

Will likely require a fix upstream in go-plugin.
func (s *GRPCServer) Stop() {
if s.broker != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you'll likely want to do this on GracefulStop() too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good shout and looks like GracefulStop() blocks until operations are completed so should be safe to do afterwards. Updated in 3d6322f.

func (s *GRPCServer) Stop() {
if s.broker != nil {
s.broker.Close()
Copy link
Contributor

@swenson swenson Nov 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also recommend setting s.broker = nil here in case someone calls this function twice.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. Updated in 3d6322f.

Copy link
Contributor

@swenson swenson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bflad bflad merged commit 1139bff into master Nov 8, 2022
@bflad bflad deleted the bflad/GRPCServer-Stop-GRPCBroker branch November 8, 2022 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants