From 49d40b7a260c58f11a0b78eeb276cf20042f0dbe Mon Sep 17 00:00:00 2001 From: Mohammed Ahmed Date: Wed, 18 Sep 2019 16:18:49 +0530 Subject: [PATCH] Replace dumb-init with go init (#35) * Moving to use go-init instead of dumb-init Signed-off-by: Mohammed Zeeshan Ahmed * Moving go-init out of vendor and updating Dockerfile accordingly * Commenting out everything that has to do with dumb-init from Dockerfile * Removing dumb-init and any remaining references * Updating image to follow /go/src/github.com/pablo-ruth/go-init --- Dockerfile | 22 +- {vendor/dumb-init => go-init}/LICENSE | 12 +- go-init/README.md | 68 ++++ go-init/main.go | 188 ++++++++++ scripts/update-vendor.sh | 11 - vendor/dumb-init/CONTRIBUTING.md | 39 -- vendor/dumb-init/Dockerfile | 24 -- vendor/dumb-init/MANIFEST.in | 3 - vendor/dumb-init/Makefile | 92 ----- vendor/dumb-init/README.md | 309 ---------------- vendor/dumb-init/VERSION | 1 - vendor/dumb-init/VERSION.h | 6 - vendor/dumb-init/ci/artifact-upload | 17 - vendor/dumb-init/ci/docker | 18 - vendor/dumb-init/ci/docker-deb-test | 10 - vendor/dumb-init/ci/docker-python-test | 12 - vendor/dumb-init/ci/docker-tox-test | 13 - vendor/dumb-init/ci/gcov-build | 5 - vendor/dumb-init/ci/gcov-report | 4 - vendor/dumb-init/circle.yml | 18 - vendor/dumb-init/debian/.gitignore | 7 - vendor/dumb-init/debian/changelog | 158 --------- vendor/dumb-init/debian/clean | 2 - vendor/dumb-init/debian/compat | 1 - vendor/dumb-init/debian/control | 36 -- vendor/dumb-init/debian/copyright | 33 -- vendor/dumb-init/debian/docs | 1 - vendor/dumb-init/debian/help2man | 7 - vendor/dumb-init/debian/install | 1 - vendor/dumb-init/debian/lintian-overrides | 1 - vendor/dumb-init/debian/manpages | 1 - vendor/dumb-init/debian/rules | 34 -- vendor/dumb-init/debian/source/format | 1 - vendor/dumb-init/dumb-init.c | 333 ------------------ vendor/dumb-init/pytest.ini | 2 - vendor/dumb-init/requirements-dev.txt | 4 - vendor/dumb-init/setup.py | 136 ------- vendor/dumb-init/testing/__init__.py | 111 ------ vendor/dumb-init/testing/print_signals.py | 50 --- vendor/dumb-init/tests/__init__.py | 0 .../dumb-init/tests/child_processes_test.py | 147 -------- vendor/dumb-init/tests/cli_test.py | 148 -------- vendor/dumb-init/tests/conftest.py | 48 --- vendor/dumb-init/tests/exit_status_test.py | 36 -- .../dumb-init/tests/proxies_signals_test.py | 105 ------ .../dumb-init/tests/shell_background_test.py | 57 --- vendor/dumb-init/tests/test-zombies | 19 - vendor/dumb-init/tests/tty_test.py | 118 ------- vendor/dumb-init/tox.ini | 25 -- 49 files changed, 269 insertions(+), 2225 deletions(-) rename {vendor/dumb-init => go-init}/LICENSE (87%) create mode 100644 go-init/README.md create mode 100644 go-init/main.go delete mode 100644 vendor/dumb-init/CONTRIBUTING.md delete mode 100644 vendor/dumb-init/Dockerfile delete mode 100644 vendor/dumb-init/MANIFEST.in delete mode 100644 vendor/dumb-init/Makefile delete mode 100644 vendor/dumb-init/README.md delete mode 100644 vendor/dumb-init/VERSION delete mode 100644 vendor/dumb-init/VERSION.h delete mode 100755 vendor/dumb-init/ci/artifact-upload delete mode 100644 vendor/dumb-init/ci/docker delete mode 100755 vendor/dumb-init/ci/docker-deb-test delete mode 100755 vendor/dumb-init/ci/docker-python-test delete mode 100755 vendor/dumb-init/ci/docker-tox-test delete mode 100755 vendor/dumb-init/ci/gcov-build delete mode 100755 vendor/dumb-init/ci/gcov-report delete mode 100644 vendor/dumb-init/circle.yml delete mode 100644 vendor/dumb-init/debian/.gitignore delete mode 100644 vendor/dumb-init/debian/changelog delete mode 100644 vendor/dumb-init/debian/clean delete mode 100644 vendor/dumb-init/debian/compat delete mode 100644 vendor/dumb-init/debian/control delete mode 100644 vendor/dumb-init/debian/copyright delete mode 100644 vendor/dumb-init/debian/docs delete mode 100644 vendor/dumb-init/debian/help2man delete mode 100644 vendor/dumb-init/debian/install delete mode 100644 vendor/dumb-init/debian/lintian-overrides delete mode 100644 vendor/dumb-init/debian/manpages delete mode 100755 vendor/dumb-init/debian/rules delete mode 100644 vendor/dumb-init/debian/source/format delete mode 100644 vendor/dumb-init/dumb-init.c delete mode 100644 vendor/dumb-init/pytest.ini delete mode 100644 vendor/dumb-init/requirements-dev.txt delete mode 100644 vendor/dumb-init/setup.py delete mode 100644 vendor/dumb-init/testing/__init__.py delete mode 100755 vendor/dumb-init/testing/print_signals.py delete mode 100644 vendor/dumb-init/tests/__init__.py delete mode 100644 vendor/dumb-init/tests/child_processes_test.py delete mode 100644 vendor/dumb-init/tests/cli_test.py delete mode 100644 vendor/dumb-init/tests/conftest.py delete mode 100644 vendor/dumb-init/tests/exit_status_test.py delete mode 100644 vendor/dumb-init/tests/proxies_signals_test.py delete mode 100644 vendor/dumb-init/tests/shell_background_test.py delete mode 100755 vendor/dumb-init/tests/test-zombies delete mode 100644 vendor/dumb-init/tests/tty_test.py delete mode 100644 vendor/dumb-init/tox.ini diff --git a/Dockerfile b/Dockerfile index 9e3471e..1a881e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # This is an "initContainer" image used by odo to inject required tools for odo to work properly. # -# Build Go stuff (SupervisorD and getlanguage) +# Build Go stuff (SupervisorD, getlanguage and go-init) FROM registry.svc.ci.openshift.org/openshift/release:golang-1.11 AS gobuilder @@ -16,19 +16,13 @@ ADD get-language /go/src/github.com/openshift/odo-supervisord-image/get-language WORKDIR /go/src/github.com/openshift/odo-supervisord-image/get-language RUN go build -o /tmp/getlanguage getlanguage.go - -# Build dumb-init -FROM registry.access.redhat.com/ubi7/ubi AS dumbinitbuilder -WORKDIR /tmp/dumb-init-src -RUN yum -y install gcc make binutils -COPY vendor/dumb-init /tmp/dumb-init-src -RUN gcc -std=gnu99 -s -Wall -Werror -O3 -o dumb-init dumb-init.c - +RUN mkdir -p /go/src/github.com/pablo-ruth/go-init +ADD go-init/main.go /go/src/github.com/pablo-ruth/go-init/go-init.go +RUN go build -o /tmp/go-init /go/src/github.com/pablo-ruth/go-init/go-init.go # Final image FROM registry.access.redhat.com/ubi7/ubi - LABEL com.redhat.component=atomic-openshift-odo-init-image-container \ name=openshift/odo-init-image \ io.k8s.display-name=atomic-openshift-odo-init-image \ @@ -40,10 +34,6 @@ LABEL version=0.10.0 ENV ODO_TOOLS_DIR /opt/odo-init/ -# dumb-init -COPY --from=dumbinitbuilder /tmp/dumb-init-src/dumb-init ${ODO_TOOLS_DIR}/bin/dumb-init -RUN chmod +x ${ODO_TOOLS_DIR}/bin/dumb-init - # SupervisorD RUN mkdir -p ${ODO_TOOLS_DIR}/conf ${ODO_TOOLS_DIR}/bin COPY supervisor.conf ${ODO_TOOLS_DIR}/conf/ @@ -55,9 +45,11 @@ COPY run ${ODO_TOOLS_DIR}/bin COPY s2i-setup ${ODO_TOOLS_DIR}/bin COPY setup-and-run ${ODO_TOOLS_DIR}/bin COPY vendor/fix-permissions /usr/bin/fix-permissions - COPY language-scripts ${ODO_TOOLS_DIR}/language-scripts/ + +# Get Language and go-init COPY --from=gobuilder /tmp/getlanguage ${ODO_TOOLS_DIR}/bin/getlanguage +COPY --from=gobuilder /tmp/go-init ${ODO_TOOLS_DIR}/bin/go-init RUN chgrp -R 0 ${ODO_TOOLS_DIR} && \ chmod -R g+rwX ${ODO_TOOLS_DIR} && \ diff --git a/vendor/dumb-init/LICENSE b/go-init/LICENSE similarity index 87% rename from vendor/dumb-init/LICENSE rename to go-init/LICENSE index e7b8415..6ae17f9 100644 --- a/vendor/dumb-init/LICENSE +++ b/go-init/LICENSE @@ -1,6 +1,6 @@ -The MIT License (MIT) +MIT License -Copyright (c) 2015 Yelp, Inc. +Copyright (c) 2017 Pablo RUTH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/go-init/README.md b/go-init/README.md new file mode 100644 index 0000000..13c25e5 --- /dev/null +++ b/go-init/README.md @@ -0,0 +1,68 @@ +# go-init + +[![Build Status](https://travis-ci.org/pablo-ruth/go-init.svg?branch=master)](https://travis-ci.org/pablo-ruth/go-init) + +**go-init** is a minimal init system with simple *lifecycle management* heavily inspired by [dumb-init](https://github.com/Yelp/dumb-init). + +It is designed to run as the first process (PID 1) inside a container. + +It is lightweight (less than 500KB after UPX compression) and statically linked so you don't need to install any dependency. + +## Download + +You can download the latest version on [releases page](https://github.com/pablo-ruth/go-init/releases) + +## Why you need an init system + +I can't explain it better than Yelp in *dumb-init* repo, so please [read their explanation](https://github.com/Yelp/dumb-init/blob/v1.2.0/README.md#why-you-need-an-init-system) + +Summary: +- Proper signal forwarding +- Orphaned zombies reaping + +## Why another minimal init system + +In addition to *init* problematic, **go-init** tries to solve another Docker flaw by adding *hooks* on start and stop of the main process. + +If you want to launch a command before the main process of your container and another one after the main process exit, you can't with Docker, see [issue 6982](https://github.com/moby/moby/issues/6982) + +With **go-init** you can do that with "pre" and "post" hooks. + +## Usage + +### one command + +``` +$ go-init -main "my_command param1 param2" +``` + +### pre-start and post-stop hooks + +``` +$ go-init -pre "my_pre_command param1" -main "my_command param1 param2" -post "my_post_command param1" +``` + +## docker + +Example of Dockerfile using *go-init*: +``` +FROM alpine:latest + +COPY go-init /bin/go-init + +RUN chmod +x /bin/go-init + +ENTRYPOINT ["go-init"] + +CMD ["-pre", "echo hello world", "-main", "sleep 5", "-post", "echo I finished my sleep bye"] +``` + +Build it: +``` +docker build -t go-init-example +``` + +Run it: +``` +docker run go-init-example +``` diff --git a/go-init/main.go b/go-init/main.go new file mode 100644 index 0000000..c59b7c5 --- /dev/null +++ b/go-init/main.go @@ -0,0 +1,188 @@ +package main + +import ( + "context" + "flag" + "fmt" + "log" + "os" + "os/exec" + "os/signal" + "strings" + "sync" + "syscall" + "time" +) + +var ( + versionString = "undefined" +) + +func main() { + var preStartCmd string + var mainCmd string + var postStopCmd string + var version bool + + flag.StringVar(&preStartCmd, "pre", "", "Pre-start command") + flag.StringVar(&mainCmd, "main", "", "Main command") + flag.StringVar(&postStopCmd, "post", "", "Post-stop command") + flag.BoolVar(&version, "version", false, "Display go-init version") + flag.Parse() + + if version { + fmt.Println(versionString) + os.Exit(0) + } + + if mainCmd == "" { + log.Fatal("[go-init] No main command defined, exiting") + } + + // Routine to reap zombies (it's the job of init) + ctx, cancel := context.WithCancel(context.Background()) + var wg sync.WaitGroup + wg.Add(1) + go removeZombies(ctx, &wg) + + // Launch pre-start command + if preStartCmd == "" { + log.Println("[go-init] No pre-start command defined, skip") + } else { + log.Printf("[go-init] Pre-start command launched : %s\n", preStartCmd) + err := run(preStartCmd) + if err != nil { + log.Println("[go-init] Pre-start command failed") + log.Printf("[go-init] %s\n", err) + cleanQuit(cancel, &wg, 1) + } else { + log.Printf("[go-init] Pre-start command exited") + } + } + + // Launch main command + var mainRC int + log.Printf("[go-init] Main command launched : %s\n", mainCmd) + err := run(mainCmd) + if err != nil { + log.Println("[go-init] Main command failed") + log.Printf("[go-init] %s\n", err) + mainRC = 1 + } else { + log.Printf("[go-init] Main command exited") + } + + // Launch post-stop command + if postStopCmd == "" { + log.Println("[go-init] No post-stop command defined, skip") + } else { + log.Printf("[go-init] Post-stop command launched : %s\n", postStopCmd) + err := run(postStopCmd) + if err != nil { + log.Println("[go-init] Post-stop command failed") + log.Printf("[go-init] %s\n", err) + cleanQuit(cancel, &wg, 1) + } else { + log.Printf("[go-init] Post-stop command exited") + } + } + + // Wait removeZombies goroutine + cleanQuit(cancel, &wg, mainRC) +} + +func removeZombies(ctx context.Context, wg *sync.WaitGroup) { + for { + var status syscall.WaitStatus + + // Wait for orphaned zombie process + pid, _ := syscall.Wait4(-1, &status, syscall.WNOHANG, nil) + + if pid <= 0 { + // PID is 0 or -1 if no child waiting + // so we wait for 1 second for next check + time.Sleep(1 * time.Second) + } else { + // PID is > 0 if a child was reaped + // we immediately check if another one + // is waiting + continue + } + + // Non-blocking test + // if context is done + select { + case <-ctx.Done(): + // Context is done + // so we stop goroutine + wg.Done() + return + default: + } + } +} + +func run(command string) error { + + var commandStr string + var argsSlice []string + + // Split cmd and args + commandSlice := strings.Fields(command) + commandStr = commandSlice[0] + // if there is args + if len(commandSlice) > 1 { + argsSlice = commandSlice[1:] + } + + // Register chan to receive system signals + sigs := make(chan os.Signal, 1) + defer close(sigs) + signal.Notify(sigs) + defer signal.Reset() + + // Define command and rebind + // stdout and stdin + cmd := exec.Command(commandStr, argsSlice...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + // Create a dedicated pidgroup + // used to forward signals to + // main process and all children + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + + // Goroutine for signals forwarding + go func() { + for sig := range sigs { + // Ignore SIGCHLD signals since + // thez are only usefull for go-init + if sig != syscall.SIGCHLD { + // Forward signal to main process and all children + syscall.Kill(-cmd.Process.Pid, sig.(syscall.Signal)) + } + } + }() + + // Start defined command + err := cmd.Start() + if err != nil { + return err + } + + // Wait for command to exit + err = cmd.Wait() + if err != nil { + return err + } + + return nil +} + +func cleanQuit(cancel context.CancelFunc, wg *sync.WaitGroup, code int) { + // Signal zombie goroutine to stop + // and wait for it to release waitgroup + cancel() + wg.Wait() + + os.Exit(code) +} diff --git a/scripts/update-vendor.sh b/scripts/update-vendor.sh index b999a3e..906b6a8 100755 --- a/scripts/update-vendor.sh +++ b/scripts/update-vendor.sh @@ -4,10 +4,8 @@ set +eux # Variables for version updates DUMBINIT_VERSION="1.2.2" -SUPERVISORD_VERSION="0.5" ## VDUMBINIT_VERSION="v${DUMBINIT_VERSION}" -VSUPERVISORD_VERSION="v${SUPERVISORD_VERSION}" REQUIREMENTS_DIR="$(pwd)/vendor" update_fix_permissions() { @@ -29,14 +27,6 @@ download_tar() { popd } -update_dumb_init() { - echo "Downloading dump init src" - DUMBINIT_DOWNLOAD_TARGET="${REQUIREMENTS_DIR}/dumb-init"; - DUMBINIT_DOWNLOAD="https://github.com/Yelp/dumb-init/archive/${VDUMBINIT_VERSION}.tar.gz"; - DUMBINIT_TARBALL_NAME="dumb-init-${DUMBINIT_VERSION}" - download_tar $DUMBINIT_DOWNLOAD $DUMBINIT_DOWNLOAD_TARGET $DUMBINIT_TARBALL_NAME -} - update_supervisord() { echo "Downloading supervisord src" SUPERVISORD_MOD_NAME="github.com/ochinchina/supervisord" @@ -56,5 +46,4 @@ update_supervisord() { # MAIN update_fix_permissions -update_dumb_init update_supervisord diff --git a/vendor/dumb-init/CONTRIBUTING.md b/vendor/dumb-init/CONTRIBUTING.md deleted file mode 100644 index 7864722..0000000 --- a/vendor/dumb-init/CONTRIBUTING.md +++ /dev/null @@ -1,39 +0,0 @@ -Contributing to dumb-init -======== - -`dumb-init` is primarily developed by [Yelp](https://yelp.github.io/), but -contributions are welcome from everyone! - -Code is reviewed using GitHub pull requests. To make a contribution, you should: - -1. Fork the GitHub repository -2. Push code to a branch on your fork -3. Create a pull request and wait for it to be reviewed - -We aim to have all dumb-init behavior covered by tests. If you make a change in -behavior, please add a test to ensure it doesn't regress. We're also happy to -help with suggestions on testing! - - -## Releasing new versions - -`dumb-init` uses [semantic versioning](http://semver.org/). If you're making a -contribution, please don't bump the version number yourself—we'll take care -of that after merging! - -The process to release a new version is: - -1. Update the version in `VERSION` and run `make VERSION.h` -2. Update the Debian changelog with `dch -v {new version}`. -3. Update the two `wget` urls in the README to point to the new version. -4. Commit the changes and tag the commit like `v1.0.0`. -5. `git push --tags origin master` -6. Wait for Travis to run, then find and download the binary and Debian - packages for both amd64 and ppc64el; there will be links printed at the end - of the Travis output. Put these into your `dist` directory. -7. Run `make release` -8. Run `twine upload --skip-existing dist/*.tar.gz dist/*.whl` to upload the - new version to PyPI -9. Upload the resulting Debian package, binary (inside the `dist` directory), - and sha256sums file to a new [GitHub - release](https://github.com/Yelp/dumb-init/releases) diff --git a/vendor/dumb-init/Dockerfile b/vendor/dumb-init/Dockerfile deleted file mode 100644 index 7a48e35..0000000 --- a/vendor/dumb-init/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM debian:stretch - -LABEL maintainer="Chris Kuehl " - -# The default mirrors are too flaky to run reliably in CI. -RUN sed -E \ - '/security\.debian/! s@http://[^/]+/@http://mirrors.kernel.org/@' \ - -i /etc/apt/sources.list - -# Install the bare minimum dependencies necessary for working with Debian -# packages. Build dependencies should be added under "Build-Depends" inside -# debian/control instead. -RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ - apt-get install -y --no-install-recommends \ - build-essential \ - devscripts \ - equivs \ - lintian \ - && rm -rf /var/lib/apt/lists/* && apt-get clean -WORKDIR /mnt - -ENTRYPOINT apt-get update && \ - mk-build-deps -i --tool 'apt-get --no-install-recommends -y' && \ - make builddeb diff --git a/vendor/dumb-init/MANIFEST.in b/vendor/dumb-init/MANIFEST.in deleted file mode 100644 index 2c9dd09..0000000 --- a/vendor/dumb-init/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -include dumb-init.c -include VERSION -include VERSION.h diff --git a/vendor/dumb-init/Makefile b/vendor/dumb-init/Makefile deleted file mode 100644 index 9b998f1..0000000 --- a/vendor/dumb-init/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -SHELL=bash -CFLAGS=-std=gnu99 -static -s -Wall -Werror -O3 - -TEST_PACKAGE_DEPS := build-essential python python-pip procps python-dev python-setuptools - -DOCKER_RUN_TEST := docker run -v $(PWD):/mnt:ro -VERSION = $(shell cat VERSION) - -.PHONY: build -build: VERSION.h - $(CC) $(CFLAGS) -o dumb-init dumb-init.c - -VERSION.h: VERSION - echo '// THIS FILE IS AUTOMATICALLY GENERATED' > VERSION.h - echo '// Run `make VERSION.h` to update it after modifying VERSION.' >> VERSION.h - xxd -i VERSION >> VERSION.h - -.PHONY: clean -clean: clean-tox - rm -rf dumb-init dist/ *.deb - -.PHONY: clean-tox -clean-tox: - rm -rf .tox - -.PHONY: release -release: python-dists - cd dist && \ - sha256sum --binary dumb-init_$(VERSION)_amd64.deb dumb-init_$(VERSION)_amd64 dumb-init_$(VERSION)_ppc64el.deb dumb-init_$(VERSION)_ppc64el \ - > sha256sums - -.PHONY: python-dists -python-dists: VERSION.h - python setup.py sdist - docker run \ - --user $$(id -u):$$(id -g) \ - -v $(PWD)/dist:/dist:rw \ - quay.io/pypa/manylinux1_x86_64:latest \ - bash -exc ' \ - /opt/python/cp35-cp35m/bin/pip wheel --wheel-dir /tmp /dist/*.tar.gz && \ - auditwheel repair --wheel-dir /dist /tmp/*.whl --wheel-dir /dist \ - ' - -.PHONY: builddeb -builddeb: - debuild --set-envvar=CC=musl-gcc -us -uc -b - mkdir -p dist - mv ../dumb-init_*.deb dist/ - # Extract the built binary from the Debian package - dpkg-deb --fsys-tarfile dist/dumb-init_$(VERSION)_$(shell dpkg --print-architecture).deb | \ - tar -C dist --strip=3 -xvf - ./usr/bin/dumb-init - mv dist/dumb-init dist/dumb-init_$(VERSION)_$(shell dpkg --print-architecture) - -.PHONY: builddeb-docker -builddeb-docker: docker-image - mkdir -p dist - docker run -v $(PWD):/mnt dumb-init-build - -.PHONY: docker-image -docker-image: - docker build -t dumb-init-build . - -.PHONY: test -test: - tox - tox -e pre-commit - -.PHONY: install-hooks -install-hooks: - tox -e pre-commit -- install -f --install-hooks - -ITEST_TARGETS = itest_trusty itest_xenial itest_bionic itest_stretch - -.PHONY: itest $(ITEST_TARGETS) -itest: $(ITEST_TARGETS) - -itest_trusty: _itest-ubuntu-trusty -itest_xenial: _itest-ubuntu-xenial -itest_bionic: _itest-ubuntu-bionic -itest_stretch: _itest-debian-stretch - -itest_tox: - $(DOCKER_RUN_TEST) ubuntu:bionic /mnt/ci/docker-tox-test - -_itest-%: _itest_deb-% _itest_python-% - @true - -_itest_python-%: - $(DOCKER_RUN_TEST) $(shell sed 's/-/:/' <<< "$*") /mnt/ci/docker-python-test - -_itest_deb-%: builddeb-docker - $(DOCKER_RUN_TEST) $(shell sed 's/-/:/' <<< "$*") /mnt/ci/docker-deb-test diff --git a/vendor/dumb-init/README.md b/vendor/dumb-init/README.md deleted file mode 100644 index 2899c8d..0000000 --- a/vendor/dumb-init/README.md +++ /dev/null @@ -1,309 +0,0 @@ -dumb-init -======== - -[![Travis CI](https://travis-ci.org/Yelp/dumb-init.svg?branch=master)](https://travis-ci.org/Yelp/dumb-init/) -[![PyPI version](https://badge.fury.io/py/dumb-init.svg)](https://pypi.python.org/pypi/dumb-init) - - -**dumb-init** is a simple process supervisor and init system designed to run as -PID 1 inside minimal container environments (such as [Docker][docker]). It is -deployed as a small, statically-linked binary written in C. - -Lightweight containers have popularized the idea of running a single process or -service without normal init systems like [systemd][systemd] or -[sysvinit][sysvinit]. However, omitting an init system often leads to incorrect -handling of processes and signals, and can result in problems such as -containers which can't be gracefully stopped, or leaking containers which -should have been destroyed. - -`dumb-init` enables you to simply prefix your command with `dumb-init`. It acts -as PID 1 and immediately spawns your command as a child process, taking care to -properly handle and forward signals as they are received. - - -## Why you need an init system - -Normally, when you launch a Docker container, the process you're executing -becomes PID 1, giving it the quirks and responsibilities that come with being -the init system for the container. - -There are two common issues this presents: - -1. In most cases, signals won't be handled properly. - - The Linux kernel applies special signal handling to processes which run as - PID 1. - - When processes are sent a signal on a normal Linux system, the kernel will - first check for any custom handlers the process has registered for that - signal, and otherwise fall back to default behavior (for example, killing - the process on `SIGTERM`). - - However, if the process receiving the signal is PID 1, it gets special - treatment by the kernel; if it hasn't registered a handler for the signal, - the kernel won't fall back to default behavior, and nothing happens. In - other words, if your process doesn't explicitly handle these signals, - sending it `SIGTERM` will have no effect at all. - - A common example is CI jobs that do `docker run my-container script`: sending - `SIGTERM` to the `docker run` process will typically kill the `docker run` command, - but leave the container running in the background. - -2. Orphaned zombie processes aren't properly reaped. - - A process becomes a zombie when it exits, and remains a zombie until its - parent calls some variation of the `wait()` system call on it. It remains in - the process table as a "defunct" process. Typically, a parent process will - call `wait()` immediately and avoid long-living zombies. - - If a parent exits before its child, the child is "orphaned", and is - re-parented under PID 1. The init system is thus responsible for - `wait()`-ing on orphaned zombie processes. - - Of course, most processes *won't* `wait()` on random processes that happen - to become attached to them, so containers often end with dozens of zombies - rooted at PID 1. - - -## What `dumb-init` does - -`dumb-init` runs as PID 1, acting like a simple init system. It launches a -single process and then proxies all received signals to a session rooted at -that child process. - -Since your actual process is no longer PID 1, when it receives signals from -`dumb-init`, the default signal handlers will be applied, and your process will -behave as you would expect. If your process dies, `dumb-init` will also die, -taking care to clean up any other processes that might still remain. - - -### Session behavior - -In its default mode, `dumb-init` establishes a -[session](http://man7.org/linux/man-pages/man2/setsid.2.html) rooted at the -child, and sends signals to the entire process group. This is useful if you -have a poorly-behaving child (such as a shell script) which won't normally -signal its children before dying. - -This can actually be useful outside of Docker containers in regular process -supervisors like [daemontools][daemontools] or [supervisord][supervisord] for -supervising shell scripts. Normally, a signal like `SIGTERM` received by a -shell isn't forwarded to subprocesses; instead, only the shell process dies. -With dumb-init, you can just write shell scripts with dumb-init in the shebang: - - #!/usr/bin/dumb-init /bin/sh - my-web-server & # launch a process in the background - my-other-server # launch another process in the foreground - -Ordinarily, a `SIGTERM` sent to the shell would kill the shell but leave those -processes running (both the background and foreground!). With dumb-init, your -subprocesses will receive the same signals your shell does. - -If you'd like for signals to only be sent to the direct child, you can run with -the `--single-child` argument, or set the environment variable -`DUMB_INIT_SETSID=0` when running `dumb-init`. In this mode, dumb-init is -completely transparent; you can even string multiple together (like `dumb-init -dumb-init echo 'oh, hi'`). - - -### Signal rewriting - -dumb-init allows rewriting incoming signals before proxying them. This is -useful in cases where you have a Docker supervisor (like Mesos or Kubernetes) -which always sends a standard signal (e.g. SIGTERM). Some apps require a -different stop signal in order to do graceful cleanup. - -For example, to rewrite the signal SIGTERM (number 15) to SIGQUIT (number 3), -just add `--rewrite 15:3` on the command line. - -To drop a signal entirely, you can rewrite it to the special number `0`. - - -#### Signal rewriting special case - -When running in setsid mode, it is not sufficient to forward -`SIGTSTP`/`SIGTTIN`/`SIGTTOU` in most cases, since if the process has not added -a custom signal handler for these signals, then the kernel will not apply -default signal handling behavior (which would be suspending the process) since -it is a member of an orphaned process group. For this reason, we set default -rewrites to `SIGSTOP` from those three signals. You can opt out of this -behavior by rewriting the signals back to their original values, if desired. - -One caveat with this feature: for job control signals (`SIGTSTP`, `SIGTTIN`, -`SIGTTOU`), dumb-init will always suspend itself after receiving the signal, -even if you rewrite it to something else. - - -## Installing inside Docker containers - -You have a few options for using `dumb-init`: - - -### Option 1: Installing from your distro's package repositories (Debian, Ubuntu, etc.) - -Many popular Linux distributions (including Debian (since `stretch`) and Debian -derivatives such as Ubuntu (since `bionic`)) now contain dumb-init packages in -their official repositories. - -On Debian-based distributions, you can run `apt install dumb-init` to install -dumb-init, just like you'd install any other package. - -*Note:* Most distro-provided versions of dumb-init are not statically-linked, -unlike the versions we provide (see the other options below). This is normally -perfectly fine, but means that these versions of dumb-init generally won't work -when copied to other Linux distros, unlike the statically-linked versions we -provide. - - -### Option 2: Installing via an internal apt server (Debian/Ubuntu) - -If you have an internal apt server, uploading the `.deb` to your server is the -recommended way to use `dumb-init`. In your Dockerfiles, you can simply -`apt install dumb-init` and it will be available. - -Debian packages are available from the [GitHub Releases tab][gh-releases], or -you can run `make builddeb` yourself. - - -### Option 3: Installing the `.deb` package manually (Debian/Ubuntu) - -If you don't have an internal apt server, you can use `dpkg -i` to install the -`.deb` package. You can choose how you get the `.deb` onto your container -(mounting a directory or `wget`-ing it are some options). - -One possibility is with the following commands in your Dockerfile: - -```Dockerfile -RUN wget https://github.com/Yelp/dumb-init/releases/download/v1.2.2/dumb-init_1.2.2_amd64.deb -RUN dpkg -i dumb-init_*.deb -``` - - -### Option 4: Downloading the binary directly - -Since dumb-init is released as a statically-linked binary, you can usually just -plop it into your images. Here's an example of doing that in a Dockerfile: - -```Dockerfile -RUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.2/dumb-init_1.2.2_amd64 -RUN chmod +x /usr/local/bin/dumb-init -``` - - -### Option 5: Installing from PyPI - -Though `dumb-init` is written entirely in C, we also provide a Python package -which compiles and installs the binary. It can be installed [from -PyPI](https://pypi.python.org/pypi/dumb-init) using `pip`. You'll want to first -install a C compiler (on Debian/Ubuntu, `apt-get install gcc` is sufficient), -then just `pip install dumb-init`. - -As of 1.2.0, the package at PyPI is available as a pre-built wheel archive and does not -need to be compiled on common Linux distributions. - - -## Usage - -Once installed inside your Docker container, simply prefix your commands with -`dumb-init` (and make sure that you're using [the recommended JSON -syntax][docker-cmd-json]). - -Within a Dockerfile, it's a good practice to use dumb-init as your container's -entrypoint. An "entrypoint" is a partial command that gets prepended to your -`CMD` instruction, making it a great fit for dumb-init: - -```Dockerfile -# Runs "/usr/bin/dumb-init -- /my/script --with --args" -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - -# or if you use --rewrite or other cli flags -# ENTRYPOINT ["dumb-init", "--rewrite", "2:3", "--"] - -CMD ["/my/script", "--with", "--args"] -``` - -If you declare an entrypoint in a base image, any images that descend from it -don't need to also declare dumb-init. They can just set a `CMD` as usual. - -For interactive one-off usage, you can just prepend it manually: - - $ docker run my_container dumb-init python -c 'while True: pass' - -Running this same command without `dumb-init` would result in being unable to -stop the container without `SIGKILL`, but with `dumb-init`, you can send it -more humane signals like `SIGTERM`. - -It's important that you use [the JSON syntax][docker-cmd-json] for `CMD` and -`ENTRYPOINT`. Otherwise, Docker invokes a shell to run your command, resulting -in the shell as PID 1 instead of dumb-init. - - -### Using a shell for pre-start hooks - -Often containers want to do some pre-start work which can't be done during -build time. For example, you might want to template out some config files based -on environment variables. - -The best way to integrate that with dumb-init is like this: - -```Dockerfile -ENTRYPOINT ["/usr/bin/dumb-init", "--"] -CMD ["bash", "-c", "do-some-pre-start-thing && exec my-server"] -``` - -By still using dumb-init as the entrypoint, you always have a proper init -system in place. - -The `exec` portion of the bash command is important because it [replaces the -bash process][exec] with your server, so that the shell only exists momentarily -at start. - - -## Building dumb-init - -Building the dumb-init binary requires a working compiler and libc headers and -defaults to glibc. - - $ make - - -### Building with musl - -Statically compiled dumb-init is over 700KB due to glibc, but musl is now an -option. On Debian/Ubuntu `apt-get install musl-tools` to install the source and -wrappers, then just: - - $ CC=musl-gcc make - -When statically compiled with musl the binary size is around 20KB. - - -### Building the Debian package - -We use the standard Debian conventions for specifying build dependencies (look -in `debian/control`). An easy way to get started is to `apt-get install -build-essential devscripts equivs`, and then `sudo mk-build-deps -i --remove` -to install all of the missing build dependencies automatically. You can then -use `make builddeb` to build dumb-init Debian packages. - -If you prefer an automated Debian package build using Docker, just run `make -builddeb-docker`. This is easier, but requires you to have Docker running on -your machine. - - -## See also - -* [Docker and the PID 1 zombie reaping problem (Phusion Blog)](https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/) -* [Trapping signals in Docker containers (@gchudnov)](https://medium.com/@gchudnov/trapping-signals-in-docker-containers-7a57fdda7d86) -* [tini](https://github.com/krallin/tini), an alternative to dumb-init -* [pid1](https://github.com/fpco/pid1), an alternative to dumb-init, written in Haskell - - -[daemontools]: http://cr.yp.to/daemontools.html -[docker-cmd-json]: https://docs.docker.com/engine/reference/builder/#run -[docker]: https://www.docker.com/ -[exec]: https://en.wikipedia.org/wiki/Exec_(system_call) -[gh-releases]: https://github.com/Yelp/dumb-init/releases -[supervisord]: http://supervisord.org/ -[systemd]: https://wiki.freedesktop.org/www/Software/systemd/ -[sysvinit]: https://wiki.archlinux.org/index.php/SysVinit diff --git a/vendor/dumb-init/VERSION b/vendor/dumb-init/VERSION deleted file mode 100644 index 23aa839..0000000 --- a/vendor/dumb-init/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.2.2 diff --git a/vendor/dumb-init/VERSION.h b/vendor/dumb-init/VERSION.h deleted file mode 100644 index f94943f..0000000 --- a/vendor/dumb-init/VERSION.h +++ /dev/null @@ -1,6 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED -// Run `make VERSION.h` to update it after modifying VERSION. -unsigned char VERSION[] = { - 0x31, 0x2e, 0x32, 0x2e, 0x32, 0x0a -}; -unsigned int VERSION_len = 6; diff --git a/vendor/dumb-init/ci/artifact-upload b/vendor/dumb-init/ci/artifact-upload deleted file mode 100755 index cb98a9c..0000000 --- a/vendor/dumb-init/ci/artifact-upload +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -euo pipefail - -if [ -n "${ARTIFACTS_SECRET:-}" ]; then - # Travis has built-in support for artifact uploading, but it's broken on ppc64le: - # https://github.com/travis-ci/travis-ci/issues/9710 - pip install --user awscli - - ARTIFACTS_PATH="dumb-init/${TRAVIS_BUILD_NUMBER}/${ITEST_TARGET}-${TRAVIS_OS_NAME}" - echo 'Uploading artifacts:' - for f in dist/*; do - AWS_ACCESS_KEY_ID=$ARTIFACTS_KEY AWS_SECRET_ACCESS_KEY=$ARTIFACTS_SECRET ~/.local/bin/aws \ - s3 --region $ARTIFACTS_REGION \ - cp "$f" s3://$ARTIFACTS_BUCKET/$ARTIFACTS_PATH/$(dirname "$f")/ - echo "* https://${ARTIFACTS_BUCKET}.s3.amazonaws.com/$ARTIFACTS_PATH/$f" - done -fi diff --git a/vendor/dumb-init/ci/docker b/vendor/dumb-init/ci/docker deleted file mode 100644 index 30fa861..0000000 --- a/vendor/dumb-init/ci/docker +++ /dev/null @@ -1,18 +0,0 @@ -# The default mirrors are too flaky to run reliably in CI. -sed -E \ - '/security\.debian/! s@http://[^/]+/@http://mirrors.kernel.org/@' \ - -i /etc/apt/sources.list - -apt-get update -apt-get install -y --no-install-recommends \ - build-essential \ - procps \ - python \ - python-dev \ - python-pip \ - python-setuptools - -cp -r /mnt/ /test -cd /test - -# vim: ft=sh diff --git a/vendor/dumb-init/ci/docker-deb-test b/vendor/dumb-init/ci/docker-deb-test deleted file mode 100755 index d46dcc0..0000000 --- a/vendor/dumb-init/ci/docker-deb-test +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -eux -set -o pipefail - -. /mnt/ci/docker - -dpkg -i dist/*.deb -pip install -r requirements-dev.txt -py.test tests/ - -exec dumb-init /mnt/tests/test-zombies diff --git a/vendor/dumb-init/ci/docker-python-test b/vendor/dumb-init/ci/docker-python-test deleted file mode 100755 index 5b0d369..0000000 --- a/vendor/dumb-init/ci/docker-python-test +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -eux -set -o pipefail - -. /mnt/ci/docker - -python setup.py clean -python setup.py sdist -pip install -vv dist/*.tar.gz -pip install -r requirements-dev.txt -py.test tests/ - -exec dumb-init /mnt/tests/test-zombies \ diff --git a/vendor/dumb-init/ci/docker-tox-test b/vendor/dumb-init/ci/docker-tox-test deleted file mode 100755 index 471c861..0000000 --- a/vendor/dumb-init/ci/docker-tox-test +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -eux -set -o pipefail - -. /mnt/ci/docker - -apt-get update -apt-get install -y --no-install-recommends \ - git \ - python2.7-dev \ - python3.6-dev \ - tox - -tox diff --git a/vendor/dumb-init/ci/gcov-build b/vendor/dumb-init/ci/gcov-build deleted file mode 100755 index 0940f22..0000000 --- a/vendor/dumb-init/ci/gcov-build +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -envbindir="$1" -cc -c dumb-init.c -o dumb-init.o -g --coverage -cc dumb-init.o -o "${envbindir}/dumb-init" -g --coverage diff --git a/vendor/dumb-init/ci/gcov-report b/vendor/dumb-init/ci/gcov-report deleted file mode 100755 index d5ef10a..0000000 --- a/vendor/dumb-init/ci/gcov-report +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -gcov -f dumb-init.c -grep '#####' dumb-init.c.gcov | cut -d':' -f2 | xargs echo "Missing:" diff --git a/vendor/dumb-init/circle.yml b/vendor/dumb-init/circle.yml deleted file mode 100644 index 0281c5c..0000000 --- a/vendor/dumb-init/circle.yml +++ /dev/null @@ -1,18 +0,0 @@ -machine: - services: - - docker - -dependencies: - # Without overriding, Circle CI infers that it should run `python setup.py - # install` on the host, which we don't want (instead we run all our tests - # in Docker containers). - # - # Overriding with an empty list or list with an empty string doesn't seem - # to work, so we use a little hackery. - override: - - /bin/true - -test: - override: - - ci/circle: - parallel: true diff --git a/vendor/dumb-init/debian/.gitignore b/vendor/dumb-init/debian/.gitignore deleted file mode 100644 index 99105e9..0000000 --- a/vendor/dumb-init/debian/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -/*.log -/*.substvars -/files -/substvars -/dumb-init/ -/dumb-init.1 -/debhelper-build-stamp diff --git a/vendor/dumb-init/debian/changelog b/vendor/dumb-init/debian/changelog deleted file mode 100644 index a013aa8..0000000 --- a/vendor/dumb-init/debian/changelog +++ /dev/null @@ -1,158 +0,0 @@ -dumb-init (1.2.2) unstable; urgency=medium - - * Fix a race condition which can cause the child to receive SIGHUP and - SIGCONT very shortly after start (#174). - - In general this was very rare, but some environments (especially some - container and virtualization environments) appear to encounter it at a - much higher rate, possibly due to scheduler quirks. - - -- Chris Kuehl Wed, 01 Aug 2018 16:36:22 -0700 - -dumb-init (1.2.1) unstable; urgency=medium - - * Fix verbose debug logging for ignored signals. - - Before this patch, they were reported in the verbose log as "forwarded - signal 0 to children" instead of "not forwarding signal to children". - - Since signal 0 is a noop, there is no actual behavior change here. - - Thanks @kpengboy for the patch! - - -- Chris Kuehl Fri, 01 Dec 2017 10:00:27 -0800 - -dumb-init (1.2.0) unstable; urgency=medium - - * Hand the controlling TTY to the child process, if we have one (#122). - - This fixes warnings that are printed when running a typical command like: - docker run -ti dumb-init bash - ...as well as allowing you to use job control. - - Thanks to @ehlers for the patch, and @alhafoudh (and several others) for - reporting the issue and providing details! - - -- Chris Kuehl Mon, 10 Oct 2016 14:09:57 -0700 - -dumb-init (1.1.3) unstable; urgency=low - - * Add support for FreeBSD kernel. Thanks @onlyjob for bringing this to our - attention. - - -- Chris Kuehl Tue, 02 Aug 2016 10:57:11 -0700 - -dumb-init (1.1.2) unstable; urgency=low - - * Fix race when the child exits very quickly that leads to dumb-init not - reaping the child. This should be pretty rare and most likely to happen - when dumb-init's child fails to exec (such as when you try to run a file - that doesn't exist). - - -- Chris Kuehl Mon, 25 Jul 2016 22:46:40 -0700 - -dumb-init (1.1.1) unstable; urgency=medium - - * Fix segfault when passing unknown arguments (thanks @asottile for - noticing!) (#88). - - -- Chris Kuehl Fri, 17 Jun 2016 12:11:22 -0700 - -dumb-init (1.1.0) unstable; urgency=medium - - * Add ability to rewrite incoming signals before proxying via the --rewrite - flag. Thanks @mcclurmc for the PR (#83)! - * Add ability to not rewrite incoming "suspend" job control signals in - setsid mode (#85). - * Add ability to ignore (not proxy) incoming signals (#86). - - -- Chris Kuehl Tue, 14 Jun 2016 11:45:50 -0700 - -dumb-init (1.0.3) unstable; urgency=medium - - * Fix incorrect error message when calling with bad arguments (e.g. a - command which did not exist) and passing flags (#82). - * Tag Python packages of dumb-init properly (#75). - - -- Chris Kuehl Wed, 01 Jun 2016 20:25:24 -0400 - -dumb-init (1.0.2) unstable; urgency=low - - * Rewrite signal handling to process signals synchronously (#72). - This shouldn't change behavior, but does eliminate some undefined behavior - and potential edge cases (especially race conditions). - Thanks @msavage20 for the bug report (again)! - - -- Chris Kuehl Mon, 02 May 2016 10:59:14 -0700 - -dumb-init (1.0.1) unstable; urgency=low - - * Fix exit status for processes which exit due to signal (#59). - Thanks @msavage20 for the bug report! - - -- Chris Kuehl Fri, 11 Mar 2016 14:05:58 -0800 - -dumb-init (1.0.0) unstable; urgency=low - - * Compile dumb-init with musl and strip the binary of unnecessary symbols - (thanks Konrad Scherer) - * Fix some typos (thanks Anthony Sottile) - * Add a manpage to the Debian package - - -- Chris Kuehl Thu, 07 Jan 2016 15:00:19 -0800 - -dumb-init (0.5.0) unstable; urgency=low - - * Add command-line option parsing (supplements existing environment - variables). - * Prefix debug output with '[dumb-init]' - - -- Chris Kuehl Fri, 02 Oct 2015 18:12:51 -0700 - -dumb-init (0.4.0) unstable; urgency=medium - - * Properly respond to job control signals (SIGTSTP, SIGTTIN, SIGTTOU). - - This makes it possible to suspend dumb-init (and its child process) by - hitting ^Z in an interactive shell session. - - -- Chris Kuehl Tue, 29 Sep 2015 13:45:06 -0700 - -dumb-init (0.3.1) unstable; urgency=medium - - * Exit nonzero if exec() fails (such as trying to run a nonexistent process) - - -- Chris Kuehl Tue, 29 Sep 2015 11:18:12 -0700 - -dumb-init (0.3.0) unstable; urgency=low - - * Send TERM to all processes in the session when the primary child dies when - running in setsid mode. - - -- Chris Kuehl Fri, 18 Sep 2015 11:08:05 -0700 - -dumb-init (0.2.0) unstable; urgency=low - - * Use setsid for process-group behavior. This fixes tty interaction. - * Properly reap zombie processes. - - -- Kent Wills Thu, 10 Sep 2015 13:33:25 -0700 - -dumb-init (0.1.0) unstable; urgency=low - - * Add process group support - - -- Chris Kuehl Thu, 03 Sep 2015 17:55:44 -0700 - -dumb-init (0.0.2) unstable; urgency=low - - * Exit with the same exit status as the process we call. - * Print a more useful help message when called with no arguments. - - -- Chris Kuehl Thu, 06 Aug 2015 13:51:38 -0700 - -dumb-init (0.0.1) unstable; urgency=low - - * Initial release. - - -- Chris Kuehl Thu, 06 Aug 2015 13:51:38 -0700 diff --git a/vendor/dumb-init/debian/clean b/vendor/dumb-init/debian/clean deleted file mode 100644 index 29869da..0000000 --- a/vendor/dumb-init/debian/clean +++ /dev/null @@ -1,2 +0,0 @@ -tests/*.pyc -tests/*/*.pyc diff --git a/vendor/dumb-init/debian/compat b/vendor/dumb-init/debian/compat deleted file mode 100644 index ec63514..0000000 --- a/vendor/dumb-init/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/vendor/dumb-init/debian/control b/vendor/dumb-init/debian/control deleted file mode 100644 index 16d054c..0000000 --- a/vendor/dumb-init/debian/control +++ /dev/null @@ -1,36 +0,0 @@ -Source: dumb-init -Section: utils -Priority: extra -Maintainer: Chris Kuehl -Uploaders: Kent Wills -Build-Depends: - debhelper (>= 9), - help2man, - musl-tools, -## Tests: - procps, - python, - python-mock, - python-pytest, -Standards-Version: 3.9.7 -Homepage: https://github.com/Yelp/dumb-init -Vcs-Browser: https://github.com/Yelp/dumb-init -Vcs-Git: https://github.com/Yelp/dumb-init.git - -Package: dumb-init -Architecture: any -Depends: ${misc:Depends} -Description: wrapper script which proxies signals to a child - dumb-init is a simple process supervisor and init system designed to run - as PID 1 inside minimal container environments (such as Docker). - . - Lightweight containers have popularized the idea of running a single - process or service without normal init systems like systemd or sysvinit. - However, omitting an init system often leads to incorrect handling of - processes and signals, and can result in problems such as containers - which can't be gracefully stopped, or leaking containers which should - have been destroyed. - . - dumb-init acts as PID 1 and immediately spawns your command as a child - process, taking care to properly handle and forward signals as they are - received. diff --git a/vendor/dumb-init/debian/copyright b/vendor/dumb-init/debian/copyright deleted file mode 100644 index 35f66f2..0000000 --- a/vendor/dumb-init/debian/copyright +++ /dev/null @@ -1,33 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: dumb-init -Source: https://github.com/Yelp/dumb-init/ - -Files: * -Copyright: - 2015, 2016 Yelp, Inc. -License: Expat - -Files: debian/* -Copyright: - 2015, 2016 Yelp, Inc. - 2016 Dmitry Smirnov -License: Expat - -License: Expat - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - . - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. diff --git a/vendor/dumb-init/debian/docs b/vendor/dumb-init/debian/docs deleted file mode 100644 index ab1a32b..0000000 --- a/vendor/dumb-init/debian/docs +++ /dev/null @@ -1 +0,0 @@ -README* diff --git a/vendor/dumb-init/debian/help2man b/vendor/dumb-init/debian/help2man deleted file mode 100644 index 9608e9c..0000000 --- a/vendor/dumb-init/debian/help2man +++ /dev/null @@ -1,7 +0,0 @@ -[authors] -.B dumb-init -was primarily developed at Yelp. -.br -.br -For a full list of contributors, see -https://github.com/Yelp/dumb-init/graphs/contributors diff --git a/vendor/dumb-init/debian/install b/vendor/dumb-init/debian/install deleted file mode 100644 index 4343f09..0000000 --- a/vendor/dumb-init/debian/install +++ /dev/null @@ -1 +0,0 @@ -dumb-init /usr/bin/ diff --git a/vendor/dumb-init/debian/lintian-overrides b/vendor/dumb-init/debian/lintian-overrides deleted file mode 100644 index 8ff28f1..0000000 --- a/vendor/dumb-init/debian/lintian-overrides +++ /dev/null @@ -1 +0,0 @@ -dumb-init binary: statically-linked-binary diff --git a/vendor/dumb-init/debian/manpages b/vendor/dumb-init/debian/manpages deleted file mode 100644 index 29bae9f..0000000 --- a/vendor/dumb-init/debian/manpages +++ /dev/null @@ -1 +0,0 @@ -debian/dumb-init.1 diff --git a/vendor/dumb-init/debian/rules b/vendor/dumb-init/debian/rules deleted file mode 100755 index f4adeb0..0000000 --- a/vendor/dumb-init/debian/rules +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/make -f -export DEB_BUILD_MAINT_OPTIONS = hardening=+all - -%: - dh $@ - -MAN=debian/dumb-init.1 - -override_dh_clean: - $(RM) -rv .cache - dh_clean $(MAN) - -override_dh_auto_clean: - @true - -$(MAN): - help2man --name 'a minimal init system for Linux containers' \ - --no-discard-stderr \ - --include debian/help2man \ - --no-info \ - ./dumb-init > $@ - -override_dh_installman: $(MAN) - dh_installman - -override_dh_builddeb: - # Use gzip instead of xz to support older Debian/Ubuntu releases which - # might install our debs. - dh_builddeb -- -Zgzip - -override_dh_auto_test: - find . -name '*.pyc' -delete - find . -name '__pycache__' -delete - PATH=.:$$PATH timeout --signal=KILL 60 py.test -vv tests/ diff --git a/vendor/dumb-init/debian/source/format b/vendor/dumb-init/debian/source/format deleted file mode 100644 index 89ae9db..0000000 --- a/vendor/dumb-init/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (native) diff --git a/vendor/dumb-init/dumb-init.c b/vendor/dumb-init/dumb-init.c deleted file mode 100644 index f13d4cb..0000000 --- a/vendor/dumb-init/dumb-init.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * dumb-init is a simple wrapper program designed to run as PID 1 and pass - * signals to its children. - * - * Usage: - * ./dumb-init python -c 'while True: pass' - * - * To get debug output on stderr, run with '-v'. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "VERSION.h" - -#define PRINTERR(...) do { \ - fprintf(stderr, "[dumb-init] " __VA_ARGS__); \ -} while (0) - -#define DEBUG(...) do { \ - if (debug) { \ - PRINTERR(__VA_ARGS__); \ - } \ -} while (0) - -// Signals we care about are numbered from 1 to 31, inclusive. -// (32 and above are real-time signals.) -// TODO: this is likely not portable outside of Linux, or on strange architectures -#define MAXSIG 31 - -// Indices are one-indexed (signal 1 is at index 1). Index zero is unused. -// User-specified signal rewriting. -int signal_rewrite[MAXSIG + 1] = {[0 ... MAXSIG] = -1}; -// One-time ignores due to TTY quirks. 0 = no skip, 1 = skip the next-received signal. -char signal_temporary_ignores[MAXSIG + 1] = {[0 ... MAXSIG] = 0}; - -pid_t child_pid = -1; -char debug = 0; -char use_setsid = 1; - -int translate_signal(int signum) { - if (signum <= 0 || signum > MAXSIG) { - return signum; - } else { - int translated = signal_rewrite[signum]; - if (translated == -1) { - return signum; - } else { - DEBUG("Translating signal %d to %d.\n", signum, translated); - return translated; - } - } -} - -void forward_signal(int signum) { - signum = translate_signal(signum); - if (signum != 0) { - kill(use_setsid ? -child_pid : child_pid, signum); - DEBUG("Forwarded signal %d to children.\n", signum); - } else { - DEBUG("Not forwarding signal %d to children (ignored).\n", signum); - } -} - -/* - * The dumb-init signal handler. - * - * The main job of this signal handler is to forward signals along to our child - * process(es). In setsid mode, this means signaling the entire process group - * rooted at our child. In non-setsid mode, this is just signaling the primary - * child. - * - * In most cases, simply proxying the received signal is sufficient. If we - * receive a job control signal, however, we should not only forward it, but - * also sleep dumb-init itself. - * - * This allows users to run foreground processes using dumb-init and to - * control them using normal shell job control features (e.g. Ctrl-Z to - * generate a SIGTSTP and suspend the process). - * - * The libc manual is useful: - * https://www.gnu.org/software/libc/manual/html_node/Job-Control-Signals.html - * -*/ -void handle_signal(int signum) { - DEBUG("Received signal %d.\n", signum); - - if (signal_temporary_ignores[signum] == 1) { - DEBUG("Ignoring tty hand-off signal %d.\n", signum); - signal_temporary_ignores[signum] = 0; - } else if (signum == SIGCHLD) { - int status, exit_status; - pid_t killed_pid; - while ((killed_pid = waitpid(-1, &status, WNOHANG)) > 0) { - if (WIFEXITED(status)) { - exit_status = WEXITSTATUS(status); - DEBUG("A child with PID %d exited with exit status %d.\n", killed_pid, exit_status); - } else { - assert(WIFSIGNALED(status)); - exit_status = 128 + WTERMSIG(status); - DEBUG("A child with PID %d was terminated by signal %d.\n", killed_pid, exit_status - 128); - } - - if (killed_pid == child_pid) { - forward_signal(SIGTERM); // send SIGTERM to any remaining children - DEBUG("Child exited with status %d. Goodbye.\n", exit_status); - exit(exit_status); - } - } - } else { - forward_signal(signum); - if (signum == SIGTSTP || signum == SIGTTOU || signum == SIGTTIN) { - DEBUG("Suspending self due to TTY signal.\n"); - kill(getpid(), SIGSTOP); - } - } -} - -void print_help(char *argv[]) { - fprintf(stderr, - "dumb-init v%s" - "Usage: %s [option] command [[arg] ...]\n" - "\n" - "dumb-init is a simple process supervisor that forwards signals to children.\n" - "It is designed to run as PID1 in minimal container environments.\n" - "\n" - "Optional arguments:\n" - " -c, --single-child Run in single-child mode.\n" - " In this mode, signals are only proxied to the\n" - " direct child and not any of its descendants.\n" - " -r, --rewrite s:r Rewrite received signal s to new signal r before proxying.\n" - " To ignore (not proxy) a signal, rewrite it to 0.\n" - " This option can be specified multiple times.\n" - " -v, --verbose Print debugging information to stderr.\n" - " -h, --help Print this help message and exit.\n" - " -V, --version Print the current version and exit.\n" - "\n" - "Full help is available online at https://github.com/Yelp/dumb-init\n", - VERSION, - argv[0] - ); -} - -void print_rewrite_signum_help() { - fprintf( - stderr, - "Usage: -r option takes :, where " - "is between 1 and %d.\n" - "This option can be specified multiple times.\n" - "Use --help for full usage.\n", - MAXSIG - ); - exit(1); -} - -void parse_rewrite_signum(char *arg) { - int signum, replacement; - if ( - sscanf(arg, "%d:%d", &signum, &replacement) == 2 && - (signum >= 1 && signum <= MAXSIG) && - (replacement >= 0 && replacement <= MAXSIG) - ) { - signal_rewrite[signum] = replacement; - } else { - print_rewrite_signum_help(); - } -} - -void set_rewrite_to_sigstop_if_not_defined(int signum) { - if (signal_rewrite[signum] == -1) - signal_rewrite[signum] = SIGSTOP; -} - -char **parse_command(int argc, char *argv[]) { - int opt; - struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"single-child", no_argument, NULL, 'c'}, - {"rewrite", required_argument, NULL, 'r'}, - {"verbose", no_argument, NULL, 'v'}, - {"version", no_argument, NULL, 'V'}, - {NULL, 0, NULL, 0}, - }; - while ((opt = getopt_long(argc, argv, "+hvVcr:", long_options, NULL)) != -1) { - switch (opt) { - case 'h': - print_help(argv); - exit(0); - case 'v': - debug = 1; - break; - case 'V': - fprintf(stderr, "dumb-init v%s", VERSION); - exit(0); - case 'c': - use_setsid = 0; - break; - case 'r': - parse_rewrite_signum(optarg); - break; - default: - exit(1); - } - } - - if (optind >= argc) { - fprintf( - stderr, - "Usage: %s [option] program [args]\n" - "Try %s --help for full usage.\n", - argv[0], argv[0] - ); - exit(1); - } - - char *debug_env = getenv("DUMB_INIT_DEBUG"); - if (debug_env && strcmp(debug_env, "1") == 0) { - debug = 1; - DEBUG("Running in debug mode.\n"); - } - - char *setsid_env = getenv("DUMB_INIT_SETSID"); - if (setsid_env && strcmp(setsid_env, "0") == 0) { - use_setsid = 0; - DEBUG("Not running in setsid mode.\n"); - } - - if (use_setsid) { - set_rewrite_to_sigstop_if_not_defined(SIGTSTP); - set_rewrite_to_sigstop_if_not_defined(SIGTTOU); - set_rewrite_to_sigstop_if_not_defined(SIGTTIN); - } - - return &argv[optind]; -} - -// A dummy signal handler used for signals we care about. -// On the FreeBSD kernel, ignored signals cannot be waited on by `sigwait` (but -// they can be on Linux). We must provide a dummy handler. -// https://lists.freebsd.org/pipermail/freebsd-ports/2009-October/057340.html -void dummy(int signum) {} - -int main(int argc, char *argv[]) { - char **cmd = parse_command(argc, argv); - sigset_t all_signals; - sigfillset(&all_signals); - sigprocmask(SIG_BLOCK, &all_signals, NULL); - - int i = 0; - for (i = 1; i <= MAXSIG; i++) - signal(i, dummy); - - /* - * Detach dumb-init from controlling tty, so that the child's session can - * attach to it instead. - * - * We want the child to be able to be the session leader of the TTY so that - * it can do normal job control. - */ - if (use_setsid) { - if (ioctl(STDIN_FILENO, TIOCNOTTY) == -1) { - DEBUG( - "Unable to detach from controlling tty (errno=%d %s).\n", - errno, - strerror(errno) - ); - } else { - /* - * When the session leader detaches from its controlling tty via - * TIOCNOTTY, the kernel sends SIGHUP and SIGCONT to the process - * group. We need to be careful not to forward these on to the - * dumb-init child so that it doesn't receive a SIGHUP and - * terminate itself (#136). - */ - if (getsid(0) == getpid()) { - DEBUG("Detached from controlling tty, ignoring the first SIGHUP and SIGCONT we receive.\n"); - signal_temporary_ignores[SIGHUP] = 1; - signal_temporary_ignores[SIGCONT] = 1; - } else { - DEBUG("Detached from controlling tty, but was not session leader.\n"); - } - } - } - - child_pid = fork(); - if (child_pid < 0) { - PRINTERR("Unable to fork. Exiting.\n"); - return 1; - } else if (child_pid == 0) { - /* child */ - sigprocmask(SIG_UNBLOCK, &all_signals, NULL); - if (use_setsid) { - if (setsid() == -1) { - PRINTERR( - "Unable to setsid (errno=%d %s). Exiting.\n", - errno, - strerror(errno) - ); - exit(1); - } - - if (ioctl(STDIN_FILENO, TIOCSCTTY, 0) == -1) { - DEBUG( - "Unable to attach to controlling tty (errno=%d %s).\n", - errno, - strerror(errno) - ); - } - DEBUG("setsid complete.\n"); - } - execvp(cmd[0], &cmd[0]); - - // if this point is reached, exec failed, so we should exit nonzero - PRINTERR("%s: %s\n", cmd[0], strerror(errno)); - return 2; - } else { - /* parent */ - DEBUG("Child spawned with PID %d.\n", child_pid); - for (;;) { - int signum; - sigwait(&all_signals, &signum); - handle_signal(signum); - } - } -} diff --git a/vendor/dumb-init/pytest.ini b/vendor/dumb-init/pytest.ini deleted file mode 100644 index 1ea6b80..0000000 --- a/vendor/dumb-init/pytest.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pytest] -timeout = 5 diff --git a/vendor/dumb-init/requirements-dev.txt b/vendor/dumb-init/requirements-dev.txt deleted file mode 100644 index 6e596f7..0000000 --- a/vendor/dumb-init/requirements-dev.txt +++ /dev/null @@ -1,4 +0,0 @@ -mock -pre-commit>=0.5.0 -pytest -pytest-timeout diff --git a/vendor/dumb-init/setup.py b/vendor/dumb-init/setup.py deleted file mode 100644 index db4af95..0000000 --- a/vendor/dumb-init/setup.py +++ /dev/null @@ -1,136 +0,0 @@ -from __future__ import print_function - -import os.path -import subprocess -import tempfile -from distutils.command.build import build as orig_build -from distutils.core import Command - -from setuptools import Distribution -from setuptools import Extension -from setuptools import setup -from setuptools.command.install import install as orig_install - - -try: - from wheel.bdist_wheel import bdist_wheel as _bdist_wheel - - class bdist_wheel(_bdist_wheel): - - def finalize_options(self): - _bdist_wheel.finalize_options(self) - # Mark us as not a pure python package - self.root_is_pure = False - - def get_tag(self): - python, abi, plat = _bdist_wheel.get_tag(self) - # We don't contain any python source - python, abi = 'py2.py3', 'none' - return python, abi, plat -except ImportError: - bdist_wheel = None - - -class ExeDistribution(Distribution): - c_executables = () - - -class build(orig_build): - sub_commands = orig_build.sub_commands + [ - ('build_cexe', None), - ] - - -class install(orig_install): - sub_commands = orig_install.sub_commands + [ - ('install_cexe', None), - ] - - -class install_cexe(Command): - description = 'install C executables' - outfiles = () - - def initialize_options(self): - self.build_dir = self.install_dir = None - - def finalize_options(self): - # this initializes attributes based on other commands' attributes - self.set_undefined_options('build', ('build_scripts', 'build_dir')) - self.set_undefined_options( - 'install', ('install_scripts', 'install_dir')) - - def run(self): - - self.outfiles = self.copy_tree(self.build_dir, self.install_dir) - - def get_outputs(self): - return self.outfiles - - -class build_cexe(Command): - description = 'build C executables' - - def initialize_options(self): - self.build_scripts = None - self.build_temp = None - - def finalize_options(self): - self.set_undefined_options( - 'build', - ('build_scripts', 'build_scripts'), - ('build_temp', 'build_temp'), - ) - - def run(self): - # stolen and simplified from distutils.command.build_ext - from distutils.ccompiler import new_compiler - - compiler = new_compiler(verbose=True) - - print('supports -static... ', end='') - with tempfile.NamedTemporaryFile(mode='w', suffix='.c') as f: - f.write('int main(void){}\n') - f.flush() - cmd = compiler.linker_exe + [f.name, '-static', '-o', os.devnull] - with open(os.devnull, 'wb') as devnull: - if not subprocess.call(cmd, stderr=devnull): - print('yes') - link_args = ['-static'] - else: - print('no') - link_args = [] - - for exe in self.distribution.c_executables: - objects = compiler.compile(exe.sources, output_dir=self.build_temp) - compiler.link_executable( - objects, - exe.name, - output_dir=self.build_scripts, - extra_postargs=link_args, - ) - - def get_outputs(self): - return [ - os.path.join(self.build_scripts, exe.name) - for exe in self.distribution.c_executables - ] - - -setup( - name='dumb-init', - description='Simple wrapper script which proxies signals to a child', - version=open('VERSION').read().strip(), - author='Yelp', - url='https://github.com/Yelp/dumb-init/', - platforms='linux', - c_executables=[Extension('dumb-init', ['dumb-init.c'])], - cmdclass={ - 'bdist_wheel': bdist_wheel, - 'build': build, - 'build_cexe': build_cexe, - 'install': install, - 'install_cexe': install_cexe, - }, - distclass=ExeDistribution, -) diff --git a/vendor/dumb-init/testing/__init__.py b/vendor/dumb-init/testing/__init__.py deleted file mode 100644 index 24042f3..0000000 --- a/vendor/dumb-init/testing/__init__.py +++ /dev/null @@ -1,111 +0,0 @@ -import errno -import os -import re -import signal -import sys -import time -from contextlib import contextmanager -from subprocess import PIPE -from subprocess import Popen - -from py._path.local import LocalPath - - -# these signals cause dumb-init to suspend itself -SUSPEND_SIGNALS = frozenset([ - signal.SIGTSTP, - signal.SIGTTOU, - signal.SIGTTIN, -]) - -NORMAL_SIGNALS = frozenset( - set(range(1, 32)) - - set([signal.SIGKILL, signal.SIGSTOP, signal.SIGCHLD]) - - SUSPEND_SIGNALS -) - - -@contextmanager -def print_signals(args=()): - """Start print_signals and yield dumb-init process and print_signals PID.""" - proc = Popen( - ( - ('dumb-init',) + - tuple(args) + - (sys.executable, '-m', 'testing.print_signals') - ), - stdout=PIPE, - ) - line = proc.stdout.readline() - m = re.match(b'^ready \(pid: ([0-9]+)\)\n$', line) - assert m, line - - yield proc, m.group(1).decode('ascii') - - for pid in pid_tree(proc.pid): - os.kill(pid, signal.SIGKILL) - - -def child_pids(pid): - """Return a list of direct child PIDs for the given PID.""" - children = set() - for p in LocalPath('/proc').listdir(): - try: - stat = open(p.join('stat').strpath).read() - m = re.match('^\d+ \(.+?\) [a-zA-Z] (\d+) ', stat) - assert m, stat - ppid = int(m.group(1)) - if ppid == pid: - children.add(int(p.basename)) - except IOError: - # Happens when the process exits after listing it, or between - # opening stat and reading it. - pass - return children - - -def pid_tree(pid): - """Return a list of all descendant PIDs for the given PID.""" - children = child_pids(pid) - return set( - pid - for child in children - for pid in pid_tree(child) - ) | children - - -def is_alive(pid): - """Return whether a process is running with the given PID.""" - return LocalPath('/proc').join(str(pid)).isdir() - - -def process_state(pid): - """Return a process' state, such as "stopped" or "running".""" - status = LocalPath('/proc').join(str(pid), 'status').read() - m = re.search('^State:\s+[A-Z] \(([a-z]+)\)$', status, re.MULTILINE) - return m.group(1) - - -def sleep_until(fn, timeout=1.5): - """Sleep until fn succeeds, or we time out.""" - interval = 0.01 - so_far = 0 - while True: - try: - fn() - except Exception: - if so_far >= timeout: - raise - else: - break - time.sleep(interval) - so_far += interval - - -def kill_if_alive(pid, signum=signal.SIGKILL): - """Kill a process, ignoring "no such process" errors.""" - try: - os.kill(pid, signum) - except OSError as ex: - if ex.errno != errno.ESRCH: # No such process - raise diff --git a/vendor/dumb-init/testing/print_signals.py b/vendor/dumb-init/testing/print_signals.py deleted file mode 100755 index aa8e334..0000000 --- a/vendor/dumb-init/testing/print_signals.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -"""Print received signals to stdout. - -Since all signals are printed and otherwise ignored, you'll need to send -SIGKILL (kill -9) to this process to actually end it. -""" -from __future__ import print_function - -import os -import signal -import sys -import time - - -CATCHABLE_SIGNALS = frozenset( - set(range(1, 32)) - set([signal.SIGKILL, signal.SIGSTOP, signal.SIGCHLD]) -) - - -print_queue = [] -last_signal = None - - -def unbuffered_print(line): - sys.stdout.write('{0}\n'.format(line)) - sys.stdout.flush() - - -def print_signal(signum, _): - print_queue.append(signum) - - -if __name__ == '__main__': - for signum in CATCHABLE_SIGNALS: - signal.signal(signum, print_signal) - - unbuffered_print('ready (pid: {0})'.format(os.getpid())) - - # loop forever just printing signals - while True: - if print_queue: - signum = print_queue.pop() - unbuffered_print(signum) - - if signum == signal.SIGINT and last_signal == signal.SIGINT: - print('Received SIGINT twice, exiting.') - exit(0) - last_signal = signum - - time.sleep(0.01) diff --git a/vendor/dumb-init/tests/__init__.py b/vendor/dumb-init/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/dumb-init/tests/child_processes_test.py b/vendor/dumb-init/tests/child_processes_test.py deleted file mode 100644 index d04bf3a..0000000 --- a/vendor/dumb-init/tests/child_processes_test.py +++ /dev/null @@ -1,147 +0,0 @@ -import os -import re -import signal -import sys -from subprocess import PIPE -from subprocess import Popen - -import pytest - -from testing import is_alive -from testing import kill_if_alive -from testing import pid_tree -from testing import sleep_until - - -def spawn_and_kill_pipeline(): - proc = Popen(( - 'dumb-init', - 'sh', '-c', - "yes 'oh, hi' | tail & yes error | tail >&2" - )) - - def assert_living_pids(): - assert len(living_pids(pid_tree(os.getpid()))) == 6 - - sleep_until(assert_living_pids) - - pids = pid_tree(os.getpid()) - proc.send_signal(signal.SIGTERM) - proc.wait() - return pids - - -def living_pids(pids): - return set(pid for pid in pids if is_alive(pid)) - - -@pytest.mark.usefixtures('both_debug_modes', 'setsid_enabled') -def test_setsid_signals_entire_group(): - """When dumb-init is running in setsid mode, it should signal the entire - process group rooted at it. - """ - pids = spawn_and_kill_pipeline() - - def assert_no_living_pids(): - assert len(living_pids(pids)) == 0 - - sleep_until(assert_no_living_pids) - - -@pytest.mark.usefixtures('both_debug_modes', 'setsid_disabled') -def test_no_setsid_doesnt_signal_entire_group(): - """When dumb-init is not running in setsid mode, it should only signal its - immediate child. - """ - pids = spawn_and_kill_pipeline() - - def assert_four_living_pids(): - assert len(living_pids(pids)) == 4 - - sleep_until(assert_four_living_pids) - - for pid in living_pids(pids): - kill_if_alive(pid) - - -def spawn_process_which_dies_with_children(): - """Spawn a process which spawns some children and then dies without - signaling them, wrapped in dumb-init. - - Returns a tuple (child pid, child stdout pipe), where the child is - print_signals. This is useful because you can signal the PID and see if - anything gets printed onto the stdout pipe. - """ - proc = Popen( - ( - 'dumb-init', - 'sh', '-c', - - # we need to sleep before the shell exits, or dumb-init might send - # TERM to print_signals before it has had time to register custom - # signal handlers - '{python} -m testing.print_signals & sleep 0.1'.format( - python=sys.executable, - ), - ), - stdout=PIPE, - ) - proc.wait() - assert proc.returncode == 0 - - # read a line from print_signals, figure out its pid - line = proc.stdout.readline() - match = re.match(b'ready \(pid: ([0-9]+)\)\n', line) - assert match, line - child_pid = int(match.group(1)) - - # at this point, the shell and dumb-init have both exited, but - # print_signals may or may not still be running (depending on whether - # setsid mode is enabled) - - return child_pid, proc.stdout - - -@pytest.mark.usefixtures('both_debug_modes', 'setsid_enabled') -def test_all_processes_receive_term_on_exit_if_setsid(): - """If the child exits for some reason, dumb-init should send TERM to all - processes in its session if setsid mode is enabled.""" - child_pid, child_stdout = spawn_process_which_dies_with_children() - - # print_signals should have received TERM - assert child_stdout.readline() == b'15\n' - - os.kill(child_pid, signal.SIGKILL) - - -@pytest.mark.usefixtures('both_debug_modes', 'setsid_disabled') -def test_processes_dont_receive_term_on_exit_if_no_setsid(): - """If the child exits for some reason, dumb-init should not send TERM to - any other processes if setsid mode is disabled.""" - child_pid, child_stdout = spawn_process_which_dies_with_children() - - # print_signals should not have received TERM; to test this, we send it - # some other signals and ensure they were received (and TERM wasn't) - for signum in [1, 2, 3]: - os.kill(child_pid, signum) - assert child_stdout.readline() == str(signum).encode('ascii') + b'\n' - - os.kill(child_pid, signal.SIGKILL) - - -@pytest.mark.parametrize('args', [ - ('/doesnotexist',), - ('--', '/doesnotexist'), - ('-c', '/doesnotexist'), - ('--single-child', '--', '/doesnotexist'), -]) -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_fails_nonzero_with_bad_exec(args): - """If dumb-init can't exec as requested, it should exit nonzero.""" - proc = Popen(('dumb-init',) + args, stderr=PIPE) - _, stderr = proc.communicate() - assert proc.returncode != 0 - assert ( - b'[dumb-init] /doesnotexist: No such file or directory\n' - in stderr - ) diff --git a/vendor/dumb-init/tests/cli_test.py b/vendor/dumb-init/tests/cli_test.py deleted file mode 100644 index 4d90724..0000000 --- a/vendor/dumb-init/tests/cli_test.py +++ /dev/null @@ -1,148 +0,0 @@ -"""Sanity checks for command-line options.""" -import re -import signal -from subprocess import PIPE -from subprocess import Popen - -import pytest - - -@pytest.fixture -def current_version(): - return open('VERSION').read().strip() - - -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_no_arguments_prints_usage(): - proc = Popen(('dumb-init'), stderr=PIPE) - _, stderr = proc.communicate() - assert proc.returncode != 0 - assert stderr == ( - b'Usage: dumb-init [option] program [args]\n' - b'Try dumb-init --help for full usage.\n' - ) - - -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_exits_invalid_with_invalid_args(): - proc = Popen(('dumb-init', '--yolo', '/bin/true'), stderr=PIPE) - _, stderr = proc.communicate() - assert proc.returncode == 1 - assert stderr in ( - b"dumb-init: unrecognized option '--yolo'\n", # glibc - b'dumb-init: unrecognized option: yolo\n', # musl - ) - - -@pytest.mark.parametrize('flag', ['-h', '--help']) -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_help_message(flag, current_version): - """dumb-init should say something useful when called with the help flag, - and exit zero. - """ - proc = Popen(('dumb-init', flag), stderr=PIPE) - _, stderr = proc.communicate() - assert proc.returncode == 0 - assert stderr == ( - b'dumb-init v' + current_version.encode('ascii') + b'\n' - b'Usage: dumb-init [option] command [[arg] ...]\n' - b'\n' - b'dumb-init is a simple process supervisor that forwards signals to children.\n' - b'It is designed to run as PID1 in minimal container environments.\n' - b'\n' - b'Optional arguments:\n' - b' -c, --single-child Run in single-child mode.\n' - b' In this mode, signals are only proxied to the\n' - b' direct child and not any of its descendants.\n' - b' -r, --rewrite s:r Rewrite received signal s to new signal r before proxying.\n' - b' To ignore (not proxy) a signal, rewrite it to 0.\n' - b' This option can be specified multiple times.\n' - b' -v, --verbose Print debugging information to stderr.\n' - b' -h, --help Print this help message and exit.\n' - b' -V, --version Print the current version and exit.\n' - b'\n' - b'Full help is available online at https://github.com/Yelp/dumb-init\n' - ) - - -@pytest.mark.parametrize('flag', ['-V', '--version']) -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_version_message(flag, current_version): - """dumb-init should print its version when asked to.""" - - proc = Popen(('dumb-init', flag), stderr=PIPE) - _, stderr = proc.communicate() - assert proc.returncode == 0 - assert stderr == b'dumb-init v' + current_version.encode('ascii') + b'\n' - - -@pytest.mark.parametrize('flag', ['-v', '--verbose']) -def test_verbose(flag): - """dumb-init should print debug output when asked to.""" - proc = Popen(('dumb-init', flag, 'echo', 'oh,', 'hi'), stdout=PIPE, stderr=PIPE) - stdout, stderr = proc.communicate() - assert proc.returncode == 0 - assert stdout == b'oh, hi\n' - - # child/parent race to print output after the fork(), can't guarantee exact order - assert re.search(b'(^|\n)\[dumb-init\] setsid complete\.\n', stderr), stderr # child - assert re.search( # parent - ( - '(^|\n)\[dumb-init\] Child spawned with PID [0-9]+\.\n' - '.*' # child might print here - '\[dumb-init\] Received signal {signal.SIGCHLD}\.\n' - '\[dumb-init\] A child with PID [0-9]+ exited with exit status 0.\n' - '\[dumb-init\] Forwarded signal 15 to children\.\n' - '\[dumb-init\] Child exited with status 0\. Goodbye\.\n$' - ).format(signal=signal).encode('utf8'), - stderr, - re.DOTALL, - ), stderr - - -@pytest.mark.parametrize('flag1', ['-v', '--verbose']) -@pytest.mark.parametrize('flag2', ['-c', '--single-child']) -def test_verbose_and_single_child(flag1, flag2): - """dumb-init should print debug output when asked to.""" - proc = Popen(('dumb-init', flag1, flag2, 'echo', 'oh,', 'hi'), stdout=PIPE, stderr=PIPE) - stdout, stderr = proc.communicate() - assert proc.returncode == 0 - assert stdout == b'oh, hi\n' - assert re.match( - ( - '^\[dumb-init\] Child spawned with PID [0-9]+\.\n' - '\[dumb-init\] Received signal {signal.SIGCHLD}\.\n' - '\[dumb-init\] A child with PID [0-9]+ exited with exit status 0.\n' - '\[dumb-init\] Forwarded signal 15 to children\.\n' - '\[dumb-init\] Child exited with status 0\. Goodbye\.\n$' - ).format(signal=signal).encode('utf8'), - stderr, - ) - - -@pytest.mark.parametrize('extra_args', [ - ('-r',), - ('-r', ''), - ('-r', 'herp'), - ('-r', 'herp:derp'), - ('-r', '15'), - ('-r', '15::12'), - ('-r', '15:derp'), - ('-r', '15:12', '-r'), - ('-r', '15:12', '-r', '0'), - ('-r', '15:12', '-r', '1:32'), -]) -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_rewrite_errors(extra_args): - proc = Popen( - ('dumb-init',) + extra_args + ('echo', 'oh,', 'hi'), - stdout=PIPE, stderr=PIPE, - ) - stdout, stderr = proc.communicate() - assert proc.returncode == 1 - assert stderr == ( - b'Usage: -r option takes :, where ' - b'is between 1 and 31.\n' - b'This option can be specified multiple times.\n' - b'Use --help for full usage.\n' - ) diff --git a/vendor/dumb-init/tests/conftest.py b/vendor/dumb-init/tests/conftest.py deleted file mode 100644 index aa18323..0000000 --- a/vendor/dumb-init/tests/conftest.py +++ /dev/null @@ -1,48 +0,0 @@ -import os - -import mock -import pytest - - -@pytest.fixture(autouse=True, scope='function') -def clean_environment(): - """Ensure all tests start with a clean environment. - - Even if tests properly clean up after themselves, we still need this in - case the user runs tests with an already-polluted environment. - """ - with mock.patch.dict( - os.environ, - {'DUMB_INIT_DEBUG': '', 'DUMB_INIT_SETSID': ''}, - ): - yield - - -@pytest.fixture(params=['1', '0']) -def both_debug_modes(request): - with mock.patch.dict(os.environ, {'DUMB_INIT_DEBUG': request.param}): - yield - - -@pytest.fixture -def debug_disabled(): - with mock.patch.dict(os.environ, {'DUMB_INIT_DEBUG': '0'}): - yield - - -@pytest.fixture(params=['1', '0']) -def both_setsid_modes(request): - with mock.patch.dict(os.environ, {'DUMB_INIT_SETSID': request.param}): - yield - - -@pytest.fixture -def setsid_enabled(): - with mock.patch.dict(os.environ, {'DUMB_INIT_SETSID': '1'}): - yield - - -@pytest.fixture -def setsid_disabled(): - with mock.patch.dict(os.environ, {'DUMB_INIT_SETSID': '0'}): - yield diff --git a/vendor/dumb-init/tests/exit_status_test.py b/vendor/dumb-init/tests/exit_status_test.py deleted file mode 100644 index f67a17c..0000000 --- a/vendor/dumb-init/tests/exit_status_test.py +++ /dev/null @@ -1,36 +0,0 @@ -import signal -import sys -from subprocess import Popen - -import pytest - - -@pytest.mark.parametrize('exit_status', [0, 1, 2, 32, 64, 127, 254, 255]) -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_exit_status_regular_exit(exit_status): - """dumb-init should exit with the same exit status as the process that it - supervises when that process exits normally. - """ - proc = Popen(('dumb-init', 'sh', '-c', 'exit {0}'.format(exit_status))) - proc.wait() - assert proc.returncode == exit_status - - -@pytest.mark.parametrize('signal', [ - signal.SIGTERM, - signal.SIGHUP, - signal.SIGQUIT, - signal.SIGKILL, -]) -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_exit_status_terminated_by_signal(signal): - """dumb-init should exit with status 128 + signal when the child process is - terminated by a signal. - """ - # We use Python because sh is "dash" on Debian and "bash" on others. - # https://github.com/Yelp/dumb-init/issues/115 - proc = Popen(('dumb-init', sys.executable, '-c', 'import os; os.kill(os.getpid(), {0})'.format( - signal, - ))) - proc.wait() - assert proc.returncode == 128 + signal diff --git a/vendor/dumb-init/tests/proxies_signals_test.py b/vendor/dumb-init/tests/proxies_signals_test.py deleted file mode 100644 index 84048ad..0000000 --- a/vendor/dumb-init/tests/proxies_signals_test.py +++ /dev/null @@ -1,105 +0,0 @@ -import os -import signal -from itertools import chain - -import pytest - -from testing import NORMAL_SIGNALS -from testing import print_signals -from testing import process_state - - -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_proxies_signals(): - """Ensure dumb-init proxies regular signals to its child.""" - with print_signals() as (proc, _): - for signum in NORMAL_SIGNALS: - proc.send_signal(signum) - assert proc.stdout.readline() == '{0}\n'.format(signum).encode('ascii') - - -def _rewrite_map_to_args(rewrite_map): - return chain.from_iterable( - ('-r', '{0}:{1}'.format(src, dst)) for src, dst in rewrite_map.items() - ) - - -@pytest.mark.parametrize('rewrite_map,sequence,expected', [ - ( - {}, - [signal.SIGTERM, signal.SIGQUIT, signal.SIGCONT, signal.SIGINT], - [signal.SIGTERM, signal.SIGQUIT, signal.SIGCONT, signal.SIGINT], - ), - - ( - {signal.SIGTERM: signal.SIGINT}, - [signal.SIGTERM, signal.SIGQUIT, signal.SIGCONT, signal.SIGINT], - [signal.SIGINT, signal.SIGQUIT, signal.SIGCONT, signal.SIGINT], - ), - - ( - { - signal.SIGTERM: signal.SIGINT, - signal.SIGINT: signal.SIGTERM, - signal.SIGQUIT: signal.SIGQUIT, - }, - [signal.SIGTERM, signal.SIGQUIT, signal.SIGCONT, signal.SIGINT], - [signal.SIGINT, signal.SIGQUIT, signal.SIGCONT, signal.SIGTERM], - ), - - # Lowest possible and highest possible signals. - ( - {1: 31, 31: 1}, - [1, 31], - [31, 1], - ), -]) -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_proxies_signals_with_rewrite(rewrite_map, sequence, expected): - """Ensure dumb-init can rewrite signals.""" - with print_signals(_rewrite_map_to_args(rewrite_map)) as (proc, _): - for send, expect_receive in zip(sequence, expected): - proc.send_signal(send) - assert proc.stdout.readline() == '{0}\n'.format(expect_receive).encode('ascii') - - -@pytest.mark.usefixtures('both_debug_modes', 'setsid_enabled') -def test_default_rewrites_can_be_overriden_with_setsid_enabled(): - """In setsid mode, dumb-init should allow overwriting the default - rewrites (but still suspend itself). - """ - rewrite_map = { - signal.SIGTTIN: signal.SIGTERM, - signal.SIGTTOU: signal.SIGINT, - signal.SIGTSTP: signal.SIGHUP, - } - with print_signals(_rewrite_map_to_args(rewrite_map)) as (proc, _): - for send, expect_receive in rewrite_map.items(): - assert process_state(proc.pid) in ['running', 'sleeping'] - proc.send_signal(send) - - assert proc.stdout.readline() == '{0}\n'.format(expect_receive).encode('ascii') - os.waitpid(proc.pid, os.WUNTRACED) - assert process_state(proc.pid) == 'stopped' - - proc.send_signal(signal.SIGCONT) - assert proc.stdout.readline() == '{0}\n'.format(signal.SIGCONT).encode('ascii') - assert process_state(proc.pid) in ['running', 'sleeping'] - - -@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') -def test_ignored_signals_are_not_proxied(): - """Ensure dumb-init can ignore signals.""" - rewrite_map = { - signal.SIGTERM: signal.SIGQUIT, - signal.SIGINT: 0, - signal.SIGWINCH: 0, - } - with print_signals(_rewrite_map_to_args(rewrite_map)) as (proc, _): - proc.send_signal(signal.SIGTERM) - proc.send_signal(signal.SIGINT) - assert proc.stdout.readline() == '{0}\n'.format(signal.SIGQUIT).encode('ascii') - - proc.send_signal(signal.SIGWINCH) - proc.send_signal(signal.SIGHUP) - assert proc.stdout.readline() == '{0}\n'.format(signal.SIGHUP).encode('ascii') diff --git a/vendor/dumb-init/tests/shell_background_test.py b/vendor/dumb-init/tests/shell_background_test.py deleted file mode 100644 index 665adc9..0000000 --- a/vendor/dumb-init/tests/shell_background_test.py +++ /dev/null @@ -1,57 +0,0 @@ -import os -from signal import SIGCONT - -import pytest - -from testing import print_signals -from testing import process_state -from testing import sleep_until -from testing import SUSPEND_SIGNALS - - -@pytest.mark.usefixtures('both_debug_modes', 'setsid_enabled') -def test_shell_background_support_setsid(): - """In setsid mode, dumb-init should suspend itself and its children when it - receives SIGTSTP, SIGTTOU, or SIGTTIN. - """ - with print_signals() as (proc, pid): - for signum in SUSPEND_SIGNALS: - # both dumb-init and print_signals should be running or sleeping - assert process_state(pid) in ['running', 'sleeping'] - assert process_state(proc.pid) in ['running', 'sleeping'] - - # both should now suspend - proc.send_signal(signum) - - def assert_both_stopped(): - assert process_state(proc.pid) == process_state(pid) == 'stopped' - - sleep_until(assert_both_stopped) - - # and then both wake up again - proc.send_signal(SIGCONT) - assert ( - proc.stdout.readline() == '{0}\n'.format(SIGCONT).encode('ascii') - ) - assert process_state(pid) in ['running', 'sleeping'] - assert process_state(proc.pid) in ['running', 'sleeping'] - - -@pytest.mark.usefixtures('both_debug_modes', 'setsid_disabled') -def test_shell_background_support_without_setsid(): - """In non-setsid mode, dumb-init should forward the signals SIGTSTP, - SIGTTOU, and SIGTTIN, and then suspend itself. - """ - with print_signals() as (proc, _): - for signum in SUSPEND_SIGNALS: - assert process_state(proc.pid) in ['running', 'sleeping'] - proc.send_signal(signum) - assert proc.stdout.readline() == '{0}\n'.format(signum).encode('ascii') - os.waitpid(proc.pid, os.WUNTRACED) - assert process_state(proc.pid) == 'stopped' - - proc.send_signal(SIGCONT) - assert ( - proc.stdout.readline() == '{0}\n'.format(SIGCONT).encode('ascii') - ) - assert process_state(proc.pid) in ['running', 'sleeping'] diff --git a/vendor/dumb-init/tests/test-zombies b/vendor/dumb-init/tests/test-zombies deleted file mode 100755 index 653f9e7..0000000 --- a/vendor/dumb-init/tests/test-zombies +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -eux -# Spawn a zombie process, and ensure it gets reaped. -# This test is only useful when run on an empty container with -# dumb-init as PID1. -# -# We run it as the last step of the integration tests inside our Docker -# containers. Since dumb-init must run as PID 1, we don't use pytest and -# instead write it in bash (which gets executed by PID1 dumb-init). -set -o pipefail - -bash -euxc "bash -euxc 'echo i am a zombie' &" & - -sleep 1 -num_zombies=$(ps -A -o state | (grep 'Z' || true) | wc -l) - -if [ "$num_zombies" -ne 0 ]; then - echo "Expected no zombies, but instead there were ${num_zombies}." - exit 1 -fi diff --git a/vendor/dumb-init/tests/tty_test.py b/vendor/dumb-init/tests/tty_test.py deleted file mode 100644 index 3e8693d..0000000 --- a/vendor/dumb-init/tests/tty_test.py +++ /dev/null @@ -1,118 +0,0 @@ -import os -import pty -import re -import signal -import termios -import time - -import pytest - - -EOF = b'\x04' - - -def ttyflags(fd): - """normalize tty i/o for testing""" - # see: - # http://www.gnu.org/software/libc/manual/html_mono/libc.html#Output-Modes - attrs = termios.tcgetattr(fd) - attrs[1] &= ~termios.OPOST # don't munge output - attrs[3] &= ~termios.ECHO # don't echo input - termios.tcsetattr(fd, termios.TCSANOW, attrs) - - -def readall(fd): - """read until EOF""" - result = b'' - while True: - try: - chunk = os.read(fd, 1 << 10) - except OSError as error: - if error.errno == 5: # linux pty EOF - return result - else: - raise - if chunk == b'': - return result - else: - result += chunk - - -# disable debug output so it doesn't break our assertion -@pytest.mark.usefixtures('debug_disabled') -def test_tty(): - """Ensure processes under dumb-init can write successfully, given a tty.""" - pid, fd = pty.fork() - if pid == 0: - os.execvp('dumb-init', ('dumb-init', 'tac')) - else: - # write to tac via the pty and verify its output - ttyflags(fd) - assert os.write(fd, b'1\n2\n3\n') == 6 - assert os.write(fd, EOF * 2) == 2 - output = readall(fd) - assert os.waitpid(pid, 0) == (pid, 0) - - assert output == b'3\n2\n1\n', repr(output) - - -@pytest.mark.usefixtures('both_debug_modes') -@pytest.mark.usefixtures('both_setsid_modes') -def test_child_gets_controlling_tty_if_we_had_one(): - """If dumb-init has a controlling TTY, it should give it to the child. - - To test this, we make a new TTY then exec "dumb-init bash" and ensure that - the shell has working job control. - """ - pid, sfd = pty.fork() - if pid == 0: - os.execvp('dumb-init', ('dumb-init', 'bash', '-m')) - else: - ttyflags(sfd) - - # We might get lots of extra output from the shell, so print something - # we can match on easily. - assert os.write(sfd, b'echo "flags are: [[$-]]"\n') == 25 - assert os.write(sfd, b'exit 0\n') == 7 - output = readall(sfd) - assert os.waitpid(pid, 0) == (pid, 0), output - - m = re.search(b'flags are: \[\[([a-zA-Z]+)\]\]\n', output) - assert m, output - - # "m" is job control - flags = m.group(1) - assert b'm' in flags - - -def test_sighup_sigcont_ignored_if_was_session_leader(): - """The first SIGHUP/SIGCONT should be ignored if dumb-init is the session leader. - - Due to TTY quirks (#136), when dumb-init is the session leader and forks, - it needs to avoid forwarding the first SIGHUP and SIGCONT to the child. - Otherwise, the child might receive the SIGHUP post-exec and terminate - itself. - - You can "force" this race by adding a `sleep(1)` before the signal handling - loop in dumb-init's code, but it's hard to reproduce the race reliably in a - test otherwise. Because of this, we're stuck just asserting debug messages. - """ - pid, fd = pty.fork() - if pid == 0: - # child - os.execvp('dumb-init', ('dumb-init', '-v', 'sleep', '20')) - else: - # parent - ttyflags(fd) - - # send another SIGCONT to make sure only the first is ignored - time.sleep(0.5) - os.kill(pid, signal.SIGHUP) - - output = readall(fd).decode('UTF-8') - - assert 'Ignoring tty hand-off signal {}.'.format(signal.SIGHUP) in output - assert 'Ignoring tty hand-off signal {}.'.format(signal.SIGCONT) in output - - assert '[dumb-init] Forwarded signal {} to children.'.format(signal.SIGHUP) in output - assert '[dumb-init] Forwarded signal {} to children.'.format(signal.SIGCONT) not in output diff --git a/vendor/dumb-init/tox.ini b/vendor/dumb-init/tox.ini deleted file mode 100644 index 682e643..0000000 --- a/vendor/dumb-init/tox.ini +++ /dev/null @@ -1,25 +0,0 @@ -[tox] -envlist = py27,py36,gcov - -[testenv] -deps = -r{toxinidir}/requirements-dev.txt -commands = - python -m pytest - -[testenv:gcov] -skip_install = True -commands = - {toxinidir}/ci/gcov-build {envbindir} - {[testenv]commands} - {toxinidir}/ci/gcov-report - -[testenv:pre-commit] -basepython = /usr/bin/python3.6 -commands = pre-commit {posargs:run --all-files} - -[flake8] -max-line-length = 119 - -[pep8] -# autopep8 will rewrite lines to be shorter, even though we raised the length -ignore = E501