mirror of
https://github.com/peterbourgon/runsvinit.git
synced 2024-12-16 14:57:04 +00:00
Working test
This commit is contained in:
parent
05fe1d1fa6
commit
819c47186c
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,9 @@
|
|||||||
runsvinit
|
runsvinit
|
||||||
runsvinit-*-*
|
runsvinit-*-*
|
||||||
examples/runsvinit-linux-amd64*
|
examples/runsvinit-linux-amd64*
|
||||||
|
zombietest/zombie
|
||||||
|
zombietest/runsvinit
|
||||||
|
*.uptodate
|
||||||
|
|
||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
*.o
|
*.o
|
||||||
|
45
main.go
45
main.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -13,6 +14,9 @@ import (
|
|||||||
const etcService = "/etc/service"
|
const etcService = "/etc/service"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
reap := flag.Bool("reap", true, "reap orphan children")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
|
|
||||||
runsvdir, err := exec.LookPath("runsvdir")
|
runsvdir, err := exec.LookPath("runsvdir")
|
||||||
@ -35,7 +39,12 @@ func main() {
|
|||||||
log.Printf("warning: I'm not PID 1, I'm PID %d", pid)
|
log.Printf("warning: I'm not PID 1, I'm PID %d", pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
go reapAll()
|
if *reap {
|
||||||
|
log.Print("reaping zombies")
|
||||||
|
go reapLoop()
|
||||||
|
} else {
|
||||||
|
log.Print("NOT reaping zombies")
|
||||||
|
}
|
||||||
|
|
||||||
supervisor := cmd(runsvdir, etcService)
|
supervisor := cmd(runsvdir, etcService)
|
||||||
if err := supervisor.Start(); err != nil {
|
if err := supervisor.Start(); err != nil {
|
||||||
@ -53,31 +62,33 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func reapAll() {
|
// From https://github.com/ramr/go-reaper/blob/master/reaper.go
|
||||||
|
func reapLoop() {
|
||||||
c := make(chan os.Signal)
|
c := make(chan os.Signal)
|
||||||
signal.Notify(c, syscall.SIGCHLD)
|
signal.Notify(c, syscall.SIGCHLD)
|
||||||
for range c {
|
for range c {
|
||||||
go reapOne()
|
reapChildren()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// From https://github.com/ramr/go-reaper/blob/master/reaper.go
|
func reapChildren() {
|
||||||
func reapOne() {
|
|
||||||
var (
|
|
||||||
ws syscall.WaitStatus
|
|
||||||
pid int
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
for {
|
for {
|
||||||
pid, err = syscall.Wait4(-1, &ws, 0, nil)
|
var (
|
||||||
if err != syscall.EINTR {
|
ws syscall.WaitStatus
|
||||||
break
|
pid int
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
for {
|
||||||
|
pid, err = syscall.Wait4(-1, &ws, 0, nil)
|
||||||
|
if err != syscall.EINTR {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if err == syscall.ECHILD {
|
||||||
|
return // done
|
||||||
|
}
|
||||||
|
log.Printf("reaped child process %d (%+v)", pid, ws)
|
||||||
}
|
}
|
||||||
if err == syscall.ECHILD {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Printf("reaped child process %d (%+v)", pid, ws)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type signaler interface {
|
type signaler interface {
|
||||||
|
11
zombietest/Dockerfile
Normal file
11
zombietest/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
FROM alpine:latest
|
||||||
|
RUN echo "http://dl-4.alpinelinux.org/alpine/edge/testing" >>/etc/apk/repositories && \
|
||||||
|
apk add --update runit && \
|
||||||
|
rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
|
COPY zombie /
|
||||||
|
RUN mkdir -p /etc/service/zombie
|
||||||
|
COPY run-zombie /etc/service/zombie/run
|
||||||
|
|
||||||
|
COPY /runsvinit /
|
||||||
|
|
23
zombietest/Makefile
Normal file
23
zombietest/Makefile
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
.PHONY: test clean
|
||||||
|
|
||||||
|
test: .test.uptodate
|
||||||
|
./test.bash
|
||||||
|
|
||||||
|
.test.uptodate: runsvinit zombie run-zombie Dockerfile
|
||||||
|
docker build -t zombietest .
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
runsvinit: ../*.go
|
||||||
|
env GOOS=linux GOARCH=amd64 go build -o $@ github.com/peterbourgon/runsvinit
|
||||||
|
|
||||||
|
zombie: .build.uptodate
|
||||||
|
docker run --rm -v $(shell pwd):/mount zombietest-build cc -Wall -Werror -o /mount/zombie /zombie.c
|
||||||
|
|
||||||
|
.build.uptodate: build/zombie.c build/Dockerfile
|
||||||
|
docker build -t zombietest-build build/
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf .test.uptodate .build.uptodate runsvinit zombie
|
||||||
|
docker stop zombietest zombietest-build >/dev/null 2>&1 || true
|
||||||
|
docker rm zombietest zombietest-build >/dev/null 2>&1 || true
|
24
zombietest/README.md
Normal file
24
zombietest/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# zombietest
|
||||||
|
|
||||||
|
This directory contains an integration test to prove runsvinit is actually
|
||||||
|
reaping zombies. `make` builds and executes the test as follows:
|
||||||
|
|
||||||
|
1. We produce a linux/amd64 runsvinit binary by setting GOOS/GOARCH and
|
||||||
|
invoking the Go compiler. Requires Go 1.5, or Go 1.4 built with the
|
||||||
|
appropriate cross-compile options.
|
||||||
|
|
||||||
|
2. The build/zombie.c program spawns five zombies and exits. We compile it for
|
||||||
|
linux/amd64 via a zombietest-build container. We do this so `make` works
|
||||||
|
from a Mac. This requires a working Docker installation.
|
||||||
|
|
||||||
|
3. Once we have linux/amd64 runsvinit and zombie binaries, we produce a
|
||||||
|
zombietest container via the Dockerfile. That container contains a single
|
||||||
|
runit service, /etc/service/zombie, which supervises the zombie binary. We
|
||||||
|
provide no default ENTRYPOINT, so we can supply it at runtime.
|
||||||
|
|
||||||
|
4. Once the zombietest container is built, we invoke the test.bash script.
|
||||||
|
That launches a version of the container with runsvinit set to NOT reap
|
||||||
|
zombies, and after 1 second, verifies that zombies exist. Then, it launches
|
||||||
|
a version of the container with runsvinit set to reap zombies, and after 1
|
||||||
|
second, verifies that no zombies exist.
|
||||||
|
|
@ -1,9 +1,3 @@
|
|||||||
FROM golang:1.5.1
|
FROM alpine:latest
|
||||||
|
RUN apk add --update gcc musl-dev && rm -rf /var/cache/apk/*
|
||||||
COPY ../../*.go /go/src/github.com/peterbourgon/runsvinit
|
|
||||||
RUN go install -v github.com/peterbourgon/runsvinit
|
|
||||||
RUN mv /go/bin/runsvinit /mount/
|
|
||||||
|
|
||||||
COPY zombie.c /
|
COPY zombie.c /
|
||||||
RUN cc -Wall -Werror -o /zombie /zombie.c
|
|
||||||
RUN mv /zombie /mount/
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
.PHONY: all
|
|
||||||
all: zombie runsvinit
|
|
||||||
|
|
||||||
zombie runsvinit: .uptodate
|
|
||||||
docker run -ti --rm -v $(shell pwd):/mount zombie-build
|
|
||||||
|
|
||||||
.uptodate: Dockerfile ../../*.go
|
|
||||||
docker build -t zombie-build .
|
|
||||||
touch $@
|
|
@ -1,18 +1,18 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int main ()
|
int main() {
|
||||||
{
|
pid_t pid;
|
||||||
pid_t child_pid;
|
int i;
|
||||||
|
for (i = 0; i<5; i++) {
|
||||||
child_pid = fork ();
|
pid = fork();
|
||||||
if (child_pid > 0) {
|
if (pid > 0) {
|
||||||
sleep (60);
|
printf("Zombie #%d born\n", i + 1);
|
||||||
}
|
} else {
|
||||||
else {
|
printf("Brains...\n");
|
||||||
exit (0);
|
exit(0);
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
zombietest/run-zombie
Executable file
3
zombietest/run-zombie
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec /zombie
|
34
zombietest/test.bash
Executable file
34
zombietest/test.bash
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
RC=0
|
||||||
|
SLEEP=1
|
||||||
|
|
||||||
|
C=$(docker run -d zombietest /runsvinit -reap=false)
|
||||||
|
sleep $SLEEP
|
||||||
|
NOREAP=$(docker exec $C ps -o pid,stat | grep Z | wc -l)
|
||||||
|
echo -n without reaping, we have $NOREAP zombies...
|
||||||
|
if [ "$NOREAP" -le "0" ]
|
||||||
|
then
|
||||||
|
echo " FAIL"
|
||||||
|
RC=1
|
||||||
|
else
|
||||||
|
echo " good"
|
||||||
|
fi
|
||||||
|
docker stop $C >/dev/null
|
||||||
|
docker rm $C >/dev/null
|
||||||
|
|
||||||
|
C=$(docker run -d zombietest /runsvinit)
|
||||||
|
sleep $SLEEP
|
||||||
|
YESREAP=$(docker exec $C ps -o pid,stat | grep Z | wc -l)
|
||||||
|
echo -n with reaping, we have $YESREAP zombies...
|
||||||
|
if [ "$YESREAP" -gt "0" ]
|
||||||
|
then
|
||||||
|
echo " FAIL"
|
||||||
|
RC=1
|
||||||
|
else
|
||||||
|
echo " good"
|
||||||
|
fi
|
||||||
|
docker stop $C >/dev/null
|
||||||
|
docker rm $C >/dev/null
|
||||||
|
|
||||||
|
exit $RC
|
Loading…
Reference in New Issue
Block a user