Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

render: interrupting with Ctrl+C (SIGINT/SIGTERM) leaks Function containers, the render container, and the network

Aperta
#400 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 2 giorni

@jcogilvie ci sta già lavorando.

Dal 1/10/2026.

  • #406 di @jcogilvie — aperta

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
68/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
docker, go
Ambito
cli, devops

Direzione di ricerca

Read the deferred cleanup paths in xr/cmd.go and op/cmd.go, then inspect the signal handling in internal/terminal/spinner.go and the render command entry points. Reproduce the issue with the supplied hanging Function and Ctrl+C, and verify that the existing containers, render container, and temporary network are removed before the command exits.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug
What happened?

Interrupting crossplane render with Ctrl+C while a render is in progress leaves every Function container it
started, the crossplane internal render engine container, and the temporary crossplane-render-* network
all still running. This happens with the default runtime-docker-cleanup policy (Remove), with or
without a TTY.

All cleanup in the render commands is defer-based
(xr/cmd.go L270-L281,
op/cmd.go L210-L221),
and nothing turns SIGINT/SIGTERM into context cancellation, so the process exits before any deferred
cleanup runs. The only signal handler in the CLI is the terminal spinner's
(internal/terminal/spinner.go L291-L300),
which calls os.Exit(130) — and that skips deferred cleanup too.

Expected: an interrupted render cleans up what it created before exiting.

How can we reproduce it?

Use a Function that accepts a connection but never responds, so the render blocks long enough to interrupt:

# tagged fnlc-hang:test
FROM alpine:3.20
ENTRYPOINT ["sh","-c","exec nc -lk -p 9443 -e cat","hang"]

xr.yaml:

apiVersion: example.org/v1
kind: XThing
metadata:
  name: test-xr
spec:
  coolField: hello

comp-hang.yaml:

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: xthings.example.org
spec:
  compositeTypeRef: {apiVersion: example.org/v1, kind: XThing}
  mode: Pipeline
  pipeline:
  - step: templating
    functionRef: {name: function-go-templating}
    input:
      apiVersion: gotemplating.fn.crossplane.io/v1beta1
      kind: GoTemplate
      source: Inline
      inline:
        template: |
          apiVersion: nop.crossplane.io/v1alpha1
          kind: NopResource
          metadata:
            annotations: {gotemplating.fn.crossplane.io/composition-resource-name: nop}
          spec: {forProvider: {}}
  - step: hang
    functionRef: {name: function-hang}

functions-hang.yaml (names set only to make leftovers easy to find):

apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
  name: function-go-templating
  annotations: {render.crossplane.io/runtime-docker-name: fnlc-sigint-gotmpl}
spec: {package: xpkg.crossplane.io/crossplane-contrib/function-go-templating:v0.11.0}
---
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
  name: function-hang
  annotations:
    render.crossplane.io/runtime-docker-name: fnlc-sigint-hang
    render.crossplane.io/runtime-docker-image: fnlc-hang:test
    render.crossplane.io/runtime-docker-pull-policy: Never
spec: {package: example.org/unused:v0.0.0}

Run it, press Ctrl+C after a few seconds, then look:

$ crossplane render xr.yaml comp-hang.yaml functions-hang.yaml
^C
$ echo $?
130
$ docker ps --filter name=fnlc-sigint --format '{{.Names}} {{.Status}}'
fnlc-sigint-hang Up 7 seconds
fnlc-sigint-gotmpl Up 8 seconds
$ docker network inspect crossplane-render-wxjbqjcj --format '{{range .Containers}}{{.Name}} {{end}}'
musing_lamport
$ docker inspect musing_lamport --format '{{.Config.Image}} {{.State.Status}} cmd={{json .Config.Cmd}}'
xpkg.crossplane.io/crossplane/crossplane:stable running cmd=["internal","render"]

(Transcript lightly abridged: the reproduction was scripted, sending SIGINT 6s after start. It gives the
same result under a pseudo-TTY, where the spinner's handler is the one that exits.)

Possible fix: wrap the command context in signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM) so an
interrupt cancels in-flight work and lets the existing deferred cleanup run, and have the spinner cooperate
with that instead of calling os.Exit. Cleanup already runs on a detached context.Background(), so it
still works after cancellation. A second signal could force-exit immediately, as is conventional.

Some interruptions (kill -9, a crash, a CI job timeout) can never be handled in-process; #401 proposes
labels so leftovers from those can be found and swept.

What environment did it happen in?
  • Crossplane CLI version: built from main @ 29316fea54f2ede9d2c039d9c54f0c29cbad4b65
  • Platform (e.g., linux/amd64): darwin/arm64, Docker Engine 29.5.3 (Rancher Desktop)
  • Crossplane version (if applicable): render engine image xpkg.crossplane.io/crossplane/crossplane:stable
Lingua principale
Go
Stelle
19
Fork
33
Merge medio
3g 4h
PR unite (30g)
40

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di crossplane/cli

Tutte le issue di crossplane/cli

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.