Help understanding go-plugin graceful exit for custom plugin sdk in another language

Hi all,

First time poster here!

I need some help understanding the flow of the terraform GRPC protocol, or really how the terraform plugin works at all. The crux of the problem is that I’m really bad at reading golang :sweat_smile:. This problem might be more in the domain of go-plugin than terraform, so feel free to redirect me to the appropriate place to post this question.

So, I’m writing a custom plugin sdk in javascript. It’s not done or polished or even significantly useful apart from being a fun toy for me to play with, but essentially it implements the tfplugin5.proto grpc schema in javascript as a package. I’ve got it working for all the provider/resource procedures, so you can write up a neat little provider in javascript, provide an executable entry-point and have it behave somewhat like a normal plugin.

Problem is, it doesn’t exit cleanly:

2020-06-22T00:30:53.737+1000 [WARN]  plugin: plugin failed to exit gracefully
2020-06-22T00:30:53.743+1000 [DEBUG] plugin: plugin process exited: path=/Users/lukekaalim/projects/teamcity-plugin/example/terraform-provider-teamcity pid=34591 error="signal: killed"

So, from what I’m able to discern from the source code is that there is some expectation of the plugin to send (or receive?) some sort of indication that it was able to shutdown successfully.

If we don’t perform the signal, then after 2 seconds the plugin is forcefully exited. This is fine; so far I don’t have any resources that need cleaning up, so an ungraceful exit doesnt stop my program. It does slow it down by 2 seconds every invocation, which is annoying me a little, so I was wondering what I needed to do to actually exit gracefully.


In the tfplugin5.proto file that I’m working off, there seems to be some sort of clearly documented method that involves a graceful exit.

Screen Shot 2020-06-22 at 12.51.31 am

But I’m at a bit of a loss as to exactly what to do here:

  • Should I exit the process myself when I receive this message?
  • Should I respond without the Error property to indicate there’s nothing wrong with me shutting down?
  • Should I exit during or after I receive this message?

More bizarrely, I can’t seem to observe this method being called in my plugin:


I’ve implemented a logging function (logging into a separate file), but I just can’t seem to see any entries in any logs that I set up that would indicate this method being called.

There is a chance that there’s simply a registration issue with my plugin, and that it’s an internal error that I’m missing, but even still I’d like to know more about the plugin shutdown process in general instead of reaching out in the dark.

Normally I’d refer to the source code, but this time I can seem to follow it far enough to figure out what the actual process is (hence my mention of being bad at reading golang :confounded:). This is more of a flaw with my understanding of the go-plugin and terraform core repositories themselves than any technical issues, but I’ve been butting my head against the wall for the last couple of days and figure I may as well ask for help.

So yeah! I’m just looking to shave of some seconds of runtime to make it nice and snappy, so it’s not wildly urgent nor an bug or real issue, but if anyone has a few moment of time that would be able to illuminate how graceful shutdowns work in relation to go-plugin and terraform, your comments would be appreciated.

Thanks for reading,
Luke Kaalim

So you need anything returned from c.doneCtx.Done() channel. Have you found how to send something into it?