Merge branch 'ckuehl_build_and_tests_in_docker'
This commit is contained in:
commit
0b09f86af6
14 changed files with 234 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
dumb-init
|
||||
dist/
|
||||
*.deb
|
10
Dockerfile
Normal file
10
Dockerfile
Normal file
|
@ -0,0 +1,10 @@
|
|||
FROM debian:jessie
|
||||
|
||||
MAINTAINER Chris Kuehl <ckuehl@yelp.com>
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential devscripts equivs && \
|
||||
apt-get clean
|
||||
WORKDIR /mnt
|
||||
|
||||
ENTRYPOINT mk-build-deps -i && make builddeb
|
44
Makefile
Normal file
44
Makefile
Normal file
|
@ -0,0 +1,44 @@
|
|||
DOCKER_TEST := sh -c 'dpkg -i /mnt/dist/*.deb && cd /mnt/test && ./test'
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
$(CC) -static -Wall -Werror -o dumb-init dumb-init.c
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf dumb-init dist/ *.deb
|
||||
|
||||
.PHONY: builddeb
|
||||
builddeb:
|
||||
debuild -us -uc -b
|
||||
rm -rf dist && mkdir dist
|
||||
mv ../dumb-init_*.deb dist/
|
||||
|
||||
.PHONY: builddeb-docker
|
||||
builddeb-docker: docker-image
|
||||
docker run -v $(PWD):/mnt dumb-init-build
|
||||
|
||||
.PHONY: docker-image
|
||||
docker-image:
|
||||
docker build -t dumb-init-build .
|
||||
|
||||
.PHONY: itest itest_lucid itest_precise itest_trusty itest_wheezy itest_jessie itest_stretch
|
||||
itest: itest_lucid itest_precise itest_trusty itest_wheezy itest_jessie itest_stretch
|
||||
|
||||
itest_lucid: builddeb-docker
|
||||
docker run -v $(PWD):/mnt:ro ubuntu:lucid $(DOCKER_TEST)
|
||||
|
||||
itest_precise: builddeb-docker
|
||||
docker run -v $(PWD):/mnt:ro ubuntu:precise $(DOCKER_TEST)
|
||||
|
||||
itest_trusty: builddeb-docker
|
||||
docker run -v $(PWD):/mnt:ro ubuntu:trusty $(DOCKER_TEST)
|
||||
|
||||
itest_wheezy: builddeb-docker
|
||||
docker run -v $(PWD):/mnt:ro debian:wheezy $(DOCKER_TEST)
|
||||
|
||||
itest_jessie: builddeb-docker
|
||||
docker run -v $(PWD):/mnt:ro debian:jessie $(DOCKER_TEST)
|
||||
|
||||
itest_stretch: builddeb-docker
|
||||
docker run -v $(PWD):/mnt:ro debian:stretch $(DOCKER_TEST)
|
5
debian/.gitignore
vendored
Normal file
5
debian/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
*.log
|
||||
*.substvars
|
||||
files
|
||||
substvars
|
||||
dumb-init/
|
5
debian/changelog
vendored
Normal file
5
debian/changelog
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
dumb-init (0.0.1) unstable; urgency=low
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Chris Kuehl <ckuehl@yelp.com> Wed, 29 Jul 2015 15:39:11 -0700
|
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
7
|
26
debian/control
vendored
Normal file
26
debian/control
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
Source: dumb-init
|
||||
Section: utils
|
||||
Priority: extra
|
||||
Maintainer: Chris Kuehl <ckuehl@yelp.com>
|
||||
Build-Depends: debhelper (>= 7), gcc, fakeroot
|
||||
Standards-Version: 3.9.6
|
||||
|
||||
Package: dumb-init
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}
|
||||
Description: Simple wrapper script which proxies signals to a child
|
||||
Docker runs your processes as PID1. The kernel doesn't apply default signal
|
||||
handling to PID1 processes, so if your process doesn't register a custom
|
||||
signal handler, signals like TERM will just bounce off your process.
|
||||
.
|
||||
This can result in cases where sending signals to a `docker run` process
|
||||
results in the run process exiting, but the container continuing in the
|
||||
background.
|
||||
.
|
||||
A workaround is to wrap your script in this proxy, which runs as PID1. Your
|
||||
process then runs as some other PID, and the kernel won't treat the signals
|
||||
that are proxied to them specially.
|
||||
.
|
||||
The proxy dies when your process dies, so it must not double-fork or do other
|
||||
weird things (this is basically a requirement for doing things sanely in
|
||||
Docker anyway).
|
1
debian/install
vendored
Normal file
1
debian/install
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
dumb-init /usr/bin/
|
3
debian/rules
vendored
Executable file
3
debian/rules
vendored
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/make -f
|
||||
%:
|
||||
dh $@
|
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
3.0 (native)
|
80
dumb-init.c
Normal file
80
dumb-init.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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 DUMB_INIT_DEBUG=1.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
pid_t child = -1;
|
||||
char debug = 0;
|
||||
|
||||
void signal_handler(int signum) {
|
||||
if (debug)
|
||||
fprintf(stderr, "Received signal %d.\n", signum);
|
||||
|
||||
if (child > 0) {
|
||||
kill(child, signum);
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr, "Forwarded signal to child.\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int signum;
|
||||
char* debug_env;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Try providing some arguments.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug_env = getenv("DUMB_INIT_DEBUG");
|
||||
if (debug_env && strcmp(debug_env, "1") == 0)
|
||||
debug = 1;
|
||||
|
||||
|
||||
/* register signal handlers */
|
||||
for (signum = 1; signum < 32; signum++) {
|
||||
if (signum == SIGKILL || signum == SIGSTOP || signum == SIGCHLD)
|
||||
continue;
|
||||
|
||||
if (signal(signum, signal_handler) == SIG_ERR) {
|
||||
fprintf(stderr, "Error: Couldn't register signal handler for signal `%d`. Exiting.\n", signum);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* launch our process */
|
||||
child = fork();
|
||||
|
||||
if (child < 0) {
|
||||
fprintf(stderr, "Unable to fork. Exiting.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (child == 0) {
|
||||
execvp(argv[1], &argv[1]);
|
||||
} else {
|
||||
if (debug)
|
||||
fprintf(stderr, "Child spawned with PID %d.\n", child);
|
||||
|
||||
waitpid(child, NULL, 0);
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr, "Child exited, goodbye.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
14
test/print-signals
Executable file
14
test/print-signals
Executable file
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh -eu
|
||||
# Print received signals into a file, one per line
|
||||
file="$1"
|
||||
|
||||
. ./testlib.sh
|
||||
|
||||
for i in $(catchable_signals); do
|
||||
trap "echo $i > \"$file\"" "$i"
|
||||
done
|
||||
|
||||
echo 'ready' > "$file"
|
||||
|
||||
# loop forever
|
||||
while :; do true; done
|
37
test/test
Executable file
37
test/test
Executable file
|
@ -0,0 +1,37 @@
|
|||
#!/bin/sh -eum
|
||||
# Try sending all signals via dumb-init to our `print-signals` script, ensure
|
||||
# they were all received.
|
||||
. ./testlib.sh
|
||||
|
||||
# The easiest way to communicate with the background process is with a FIFO.
|
||||
# (piping spawns additional subshells and makes it hard to get the right PID)
|
||||
fifo=$(mktemp -u)
|
||||
mkfifo -m 600 "$fifo"
|
||||
dumb-init ./print-signals "$fifo" &
|
||||
pid="$!"
|
||||
|
||||
# Wait for `print-signals` to indicate it's ready.
|
||||
head -n1 "$fifo" > /dev/null
|
||||
|
||||
for expected in $(catchable_signals); do
|
||||
kill -s "$expected" "$pid"
|
||||
echo -n "Sent signal ${expected}... "
|
||||
received=$(timeout 1 head -n1 "$fifo") || {
|
||||
echo
|
||||
echo "Error: Didn't receive signal within 1 second."
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "received signal ${received}."
|
||||
|
||||
if [ "$expected" -ne "$received" ]; then
|
||||
echo "Error: Received signal $received, but expected signal $expected."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Turn off job monitoring so we don't get a spurious "[1] + Killed" printed
|
||||
set +m
|
||||
|
||||
kill -9 "$pid"
|
||||
rm "$fifo"
|
4
test/testlib.sh
Normal file
4
test/testlib.sh
Normal file
|
@ -0,0 +1,4 @@
|
|||
catchable_signals() {
|
||||
# We can't handle the signals SIGKILL=9, SIGCHLD=17, SIGSTOP=19
|
||||
seq 1 31 | grep -vE '^(9|17|19)$'
|
||||
}
|
Loading…
Reference in a new issue