Skip to content

feat(server): stop when the host asks - #5

Merged
devgianlu merged 2 commits into
mainfrom
feat/stop-on-request
Sep 30, 2026
Merged

devgianlu merged 2 commits into
mainfrom
feat/stop-on-request

Conversation

@devgianlu

Copy link
Copy Markdown
Member

@coderabbitai ignore

Two commits:

  • the server stops when its go-plugin host asks it to;
  • CI and the preset build vcpkg's dependencies release-only.

Stop when the host asks

A go-plugin host stops a plugin in three steps:

  1. it calls GRPCController.Shutdown;
  2. it waits a grace period (two seconds in go-plugin) for the process to exit;
  3. it kills the process if it has not.

This library did not serve GRPCController, so a C++ plugin answered Unimplemented and kept running. It was always killed, so nothing after Wait() in its main ever ran, and neither did the teardown there.

PluginServer now serves the controller.

  • Registered without generated code. Its one method, /plugin.GRPCController/Shutdown, takes and returns plugin.Empty, which is zero bytes on the wire. So it is registered over raw grpc::ByteBuffers, the way generated code registers a method. That needs no .proto and no code generation, so a consumer's build, a vcpkg port for instance, needs no protoc as an extra build tool.
  • Handed to the watchdog thread. The request arrives on a gRPC thread, which cannot wait for its own server to shut down. It sets a flag and wakes the parent-death watchdog thread, which calls Shutdown() as it already does when the host dies. Wait() then returns and main unwinds.

Build vcpkg's dependencies release-only

CI and the vcpkg preset built every dependency for x64-linux, vcpkg's default, which builds each dependency twice: debug and release. The host tools (protoc, grpc_cpp_plugin) share that triplet, because target and host are the same machine. CI builds Release, so nothing links the debug copies.

x64-linux-release, vcpkg's release-only triplet, is now both the target and the host triplet. Switching only the host would add a second build here rather than remove one, since the target triplet was not release-only. The example's go:generate follows protoc to the new install path.

Tested

  • All 30 tests pass.

  • New Server.StopsWhenTheHostAsks test: it calls /plugin.GRPCController/Shutdown the way go-plugin does, and expects Wait() to return with nothing else calling Shutdown().

    • It fails without the change: the call gets Unimplemented and Wait() never returns.
    • It passed 30 repeated runs of the server tests.
  • CI steps replayed from a clean vcpkg install on the new triplet, in 6 min 44 s:

    • configure;
    • build;
    • ctest;
    • the Go example's go generate and build.

    Only an x64-linux-release tree was installed.

🤖 Generated with Claude Code

devgianlu and others added 2 commits September 30, 2026 12:00
A go-plugin host stops a plugin by calling GRPCController.Shutdown and
waiting a grace period for the process to exit, then kills it. This
library did not serve that service, so a C++ plugin answered
Unimplemented, kept running, and was always killed: nothing after
Wait() in its main ever ran.

PluginServer now serves the controller. Its one method takes and
returns plugin.Empty, zero bytes on the wire, so it is registered over
raw byte buffers, the way generated code registers a method, and a
consumer's build needs no extra code generation. The request arrives
on a gRPC thread, which cannot wait for its own server to shut down,
so it hands the stop to the parent-death watchdog thread, which
already carries out the stop when the host dies.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CI and the preset built every dependency for x64-linux, vcpkg's
default, which builds each twice: debug and release. The host tools
(protoc and grpc_cpp_plugin) share that triplet, since target and host
are the same machine. CI builds Release and nothing links the debug
copies.

x64-linux-release, vcpkg's release-only triplet, is now both target
and host. Moving only the host, as the plugins did, would add a second
build here instead of removing one, because this repository's target
triplet is not release-only. The example's go:generate follows the
protoc path.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@devgianlu
devgianlu merged commit ee5f27c into main Sep 30, 2026
2 checks passed
@devgianlu
devgianlu deleted the feat/stop-on-request branch September 30, 2026 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant