runc and the OCI hooks it spawns are separate processes, so the trace
context can not reach them over ttrpc. Inject it into their environment
instead, riding on the request context via go-runc's WithExtraEnv, which
does not race with concurrent requests the way setting it on the shim
process would.
The otelttrpc interceptor extracts that context, so chain it first
explicitly instead of leaving it to plugin initialization order. Also
flush the spans the tracing plugin buffered before the shim exits.
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
A pre-2.3 containerd daemon can start a newly installed shim through the
deprecated CLI, environment, and stdin API.
The shim currently accepts that request but returns a protobuf bootstrap
result, which the old daemon cannot parse.
It treats the protobuf bytes as a socket address and fails later with a
cryptic error:
```
failed to create TTRPC connection: unsupported protocol: \b\x03\x12Yunix
```
This patch makes the shim reject the deprecated startup request before
starting and tell the user that the containerd daemon may need to be
restarted.
The 2.2 daemon includes the shim's stderr in its start error, so this
message reaches the user directly.
This explicitly removes input-side support for the deprecated startup
API, but it does not break a working standard containerd pairing.
Pre-2.3 daemons already cannot consume the response from the new shim.
After a package upgrade, a restarted daemon uses the new bootstrap API.
Custom callers that send the deprecated request format while supporting
the new protobuf response will now also be rejected.
Signed-off-by: Paweł Gronowski <git@grono.dev>
The shim package could not be used by Windows shims due to missing implementation. This commit adds the Windows implementation for the shim package.
Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
awaitPipeReady retried only when DialPipe returned os.IsNotExist or
context.DeadlineExceeded, but winio.DialPipe converts the per-attempt
deadline into winio.ErrTimeout before returning. A pipe in state 1
(ListenPipe called, Accept not yet called) causes DialPipe to block for
the full per-attempt timeout and return winio.ErrTimeout, which the old
check treated as a fatal error instead of retrying.
Also guard windows.ERROR_PIPE_BUSY explicitly to match the error checks
in containerd/nerdbox#218.
Adds a regression test that forces the state-1 to state-2 transition
race by delaying Accept past the 1-second per-attempt timeout.
Signed-off-by: Esteban Ginez <esteban.ginez@docker.com>
Allow the socket directory to be directly configured by the shim manager
with reasonable defaults when not set. The default for root users will
still be the same directory under the default state directory. For
non-root users a temp directory will be used as default if the state
directory is not owned by the user.
Signed-off-by: Derek McGowan <derek@mcg.dev>
Send the socket directory from containerd to the shim. The shim still
decides where the socket goes but can use the environment variable
passed from containerd to ensure the socket is placed in the configured
directory with proper permission.
This is needed for some rootless cases which do not have permission to
the default state directory as currently set. The directory being
hardcoded by the shim means it is currently not possible to change the
location the shim will listen at.
Signed-off-by: Derek McGowan <derek@mcg.dev>
Avoid using logrus concepts in the API, use slog style log levels with
integer values and 0 meaning the default "info" level.
Signed-off-by: Derek McGowan <derek@mcg.dev>
- Use time.NewTimer + Stop() instead of time.After to avoid timer leaks
- Treat context.DeadlineExceeded as retryable (pipe busy, not just missing)
- Wrap last dial error instead of os.ErrNotExist for better diagnostics
- Update makeConnection godoc to reflect current BootstrapResult type
Signed-off-by: Esteban Ginez <esteban.ginez@docker.com>
The shim "start" helper returns the named pipe address before the
daemon process has created the pipe via winio.ListenPipe(). On busy
Windows systems, containerd may try to connect before the pipe exists.
Add awaitPipeReady() — the start helper now polls the pipe address
(up to 5s, 10ms intervals) before writing the bootstrap result to
stdout. This follows hcsshim's readiness pattern where the shim
verifies its endpoint is ready before signaling the parent.
As a safety net, also parameterize makeConnection() with a dialer so
binary.Start() uses AnonDialer (retry) for new shims while loadShim()
keeps AnonReconnectDialer (fail-fast) for reconnects per #3659.
On Unix, awaitPipeReady() is a no-op: domain sockets appear atomically.
Signed-off-by: Esteban Ginez <esteban.ginez@docker.com>
Revert changes related to reading annotations in runc v2 shim,
because this requires a special path for runc shim. This complicates
migration to the new bootstrap API.
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
NewSocket was using the same permission mode (0600) for both the socket
file and its parent directory.
Directories require the execute bit to be traversable, so creating a
directory with 0600 prevents any files from being created inside it.
Use 0700 for directory creation while keeping 0600 for socket files.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Currently the tests fail on Linux:
```
--- FAIL: TestNewSocket (0.00s)
--- FAIL: TestNewSocket/socket_in_nested_directory (0.00s)
util_unix_test.go:42: NewSocket failed: mkdir failed for /tmp/shim-test-1791693890/a/b/test.sock: mkdir /tmp/shim-test-1791693890/a/b: permission denied
FAIL
FAIL github.com/containerd/containerd/v2/pkg/shim 0.004s
FAIL
```
This is fixed by the next commit.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
All other binaries have both a `-v` and `--version` flag. Add a long-form
'--version' flag for this binary, useful to perform a quick check if the
binary is "functional".
Before this:
containerd-shim-runc-v2 --help
# ...
-socket string
socket path to serve
-v show the shim version and exit
After this:
containerd-shim-runc-v2 --help
# ...
-socket string
socket path to serve
-v
-version
show the shim version and exit
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Makes the pprof server a plugin and also gates by the `shim_tracing`
build tag (like otel is).
With this change, `net/http` is no longer a dependency in the shim.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This makes it so we don't need to import otelttrpc unless the shim is
compiled with the `shim_tracing` build tag.
This way otel is no longer compiled into the binary at all unless
`shim_tracing` is set.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This adds trace context propagation over the grpc/ttrpc calls to a shim.
It also adds the otlp plugin to the runc shim so that it will send
traces to the configured tracer (which is inherited from containerd's
config).
It doesn't look like this is adding any real overhead to the runc shim's
memory usage, however it does add 2MB to the binary size.
As such this is gated by a build tag `shim_tracing`
Signed-off-by: Brian Goff <cpuguy83@gmail.com>