diff --git a/build/pause/Makefile b/build/pause/Makefile index 69e92028d00..6739d5cdf3b 100644 --- a/build/pause/Makefile +++ b/build/pause/Makefile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -.PHONY: all push push-legacy container clean +.PHONY: all push push-legacy container clean orphan REGISTRY ?= gcr.io/google_containers IMAGE = $(REGISTRY)/pause-$(ARCH) @@ -25,7 +25,7 @@ ARCH ?= amd64 ALL_ARCH = amd64 arm arm64 ppc64le s390x -CFLAGS = -Os -Wall -static +CFLAGS = -Os -Wall -Werror -static KUBE_CROSS_IMAGE ?= gcr.io/google_containers/kube-cross KUBE_CROSS_VERSION ?= $(shell cat ../build-image/cross/VERSION) @@ -97,5 +97,16 @@ ifeq ($(ARCH),amd64) endif touch $@ +# Useful for testing, not automatically included in container image +orphan: bin/orphan-$(ARCH) +bin/orphan-$(ARCH): orphan.c + mkdir -p bin + docker run -u $$(id -u):$$(id -g) -v $$(pwd):/build \ + $(KUBE_CROSS_IMAGE):$(KUBE_CROSS_VERSION) \ + /bin/bash -c "\ + cd /build && \ + $(TRIPLE)-gcc $(CFLAGS) -o $@ $^ && \ + $(TRIPLE)-strip $@" + clean: rm -rf .container-* .push-* bin/ diff --git a/build/pause/orphan.c b/build/pause/orphan.c new file mode 100644 index 00000000000..07f490de91d --- /dev/null +++ b/build/pause/orphan.c @@ -0,0 +1,36 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/* Creates a zombie to be reaped by init. Useful for testing. */ + +#include +#include + +int main() { + pid_t pid; + pid = fork(); + if (pid == 0) { + while (getppid() > 1) + ; + printf("Child exiting: pid=%d ppid=%d\n", getpid(), getppid()); + return 0; + } else if (pid > 0) { + printf("Parent exiting: pid=%d ppid=%d\n", getpid(), getppid()); + return 0; + } + perror("Could not create child"); + return 1; +} diff --git a/build/pause/pause.c b/build/pause/pause.c index ffbceb69fbe..f9853915f82 100644 --- a/build/pause/pause.c +++ b/build/pause/pause.c @@ -17,20 +17,36 @@ limitations under the License. #include #include #include +#include +#include #include static void sigdown(int signo) { - psignal(signo, "shutting down, got signal"); - exit(0); + psignal(signo, "Shutting down, got signal"); + exit(0); +} + +static void sigreap(int signo) { + while (waitpid(-1, NULL, WNOHANG) > 0) + ; } int main() { - if (signal(SIGINT, sigdown) == SIG_ERR) - return 1; - if (signal(SIGTERM, sigdown) == SIG_ERR) - return 2; - signal(SIGKILL, sigdown); - for (;;) pause(); - fprintf(stderr, "error: infinite loop terminated\n"); - return 42; + if (getpid() != 1) + /* Not an error because pause sees use outside of infra containers. */ + fprintf(stderr, "Warning: pause should be the first process in a pod\n"); + + if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) + return 1; + if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) + return 2; + if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap, + .sa_flags = SA_NOCLDSTOP}, + NULL) < 0) + return 3; + + for (;;) + pause(); + fprintf(stderr, "Error: infinite loop terminated\n"); + return 42; }