Code Monkey home page Code Monkey logo

catatonit's Introduction

catatonit

Build Status

A container init that is so simple it's effectively brain-dead. This is a rewrite of initrs in C, because we found that it is not possible to statically compile Rust binaries without using musl. That was, in turn, a reimplementation of other container inits like tini and dumb-init.

The reason for re-implementing docker-init is because it appears as though all of the other implementations do not handle signals as correctly as they should. In particular, they all appear to make use of sigwait(2) (tini does a sigtimedwait(2) for an interval and then will do a waitpid(2) even if it didn't detect a SIGCHLD). catatonit uses signalfd(2), which has its own warts, but the improvements over sigwait(2) are significant in terms of stability. Ideally we would just write a patch for the other projects to use signalfd(2) rather than creating a new project, but after some time spent looking at tini and dumb-init we felt that such patches would be closer to full rewrites.

In addition, the purpose of catatonit is to only support the key usage by docker-init which is /dev/init -- <your program>. With few exceptions, no other features will be added.

Usage

catatonit has identical usage to other basic docker-init's -- you give it the command and list of arguments to that command. If catatonit is not pid1, it will try to use the sub-reaper support in the kernel. You can pass -g if you want signals to be forwarded to the entire process group of your spawned process (otherwise it's just forwarded to the process spawned).

If you wish to use catatonit as a convenient pause container (do not spawn a child process nor do any signal handling), use pass -P.

Installation

catatonit uses autotools for building, so building is a fairly standard:

% ./autogen.sh
% ./configure
% make
% sudo make install

License

catatonit is licensed under the GNU General Public License version 2 or later.

catatonit: a container init so simple it's effectively brain-dead
Copyright (C) 2018-2023 SUSE LLC

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

catatonit's People

Contributors

cyphar avatar erosennin avatar ffontaine avatar giuseppe avatar mssola avatar rubencaro avatar t-nelis avatar terceiro avatar vrothberg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

catatonit's Issues

add build instructions

I am not very familiar with autoconf and always have to Google how to use it. Some build instructions in the README would be great :)

Catatonit Version String: Is this a bug?

Please can someone explain the version string:-

$ catatonit --version
tini version 0.2.0_catatonit

It looks like some sort of bug, string error!

Can't we have something more conventional like:-

$ conmon --version
conmon version 2.1.10
commit: 09bcded8e9c49cf1ff1fda403feac5a08f22535f-dirty

I can then parse it better in my script using lastversion

FreeBSD support?

As part of my work on podman last year, I made a quick-and-dirty port of catatonit, mostly around using kqueue instead of signalfd for events and procctl instead of prctl for child subreaper support. If there is any interest in merging this, I can take some time to clean this up and make a PR.

catatonit keeps a mount directory open, preventing unmounting

Debian bookworm (lite, headless) on a Raspberry Pi, using podman, although no containers are running.

We have a directory that is a cifs mount of an SMB file system (from a Mac). We could not unmount the directory because it was busy. lsof showed that a catatonit process/thread (related to podman, I believe) was holding the directory open.

I can imagine that catatonit is interested in mounted file systems, but, I would not expect catatonit to be so intrusive as to hold a file/directory open, thus prevent unmounting.

Regards

catatonit hangs due to signal coalescing

Steps to reproduce:

$ CATATONIT_DEBUG=1 catatonit -- bash -c "bash -c 'sleep 0.01 & kill -9 \$BASHPID'; sleep 0.0087"
DEBUG (catatonit:24487): pid1 (24488) spawned: bash
bash: line 1: 24489 Killed                  bash -c 'sleep 0.01 & kill -9 $BASHPID'
DEBUG (catatonit:24487): child process 24488 exited with code 0
DEBUG (catatonit:24487): child process 24491 exited with code 0
DEBUG (catatonit:24487): got ECHILD: no children left to monitor
(hangs forever)

You may have to fiddle with the final sleep value to reproduce. Binary search for a number such that you see one "child process exited" message half the time and two half the time, and then run it repeatedly until it freezes. (The goal is for the inner sleep to end just before the outer one. I'm sure you could write a fully reliable reproduction using a freezer cgroup or something like that.)

When multiple children of catatonit terminate at nearly the same time, signal coalescing means that only one SIGCHLD is guaranteed to be delivered, and it might not be the one corresponding to the "pid1" process. catatonit correctly runs waitpid in a loop and reaps all of the terminated processes, but it only notices pid1 termination when that SIGCHLD happens to be the one that is delivered.

I think the "special case for pid1" needs to be moved into the loop in reap_zombies().

alpine build fails due to configure syntax error

On alpine ./configure fails due to a syntax error:

./configure: line 3156: syntax error: unexpected word (expecting ")")

configure line 3153-3157:

fi


LT_PREREQ(2.4.2)
LT_INIT(disable-shared)

Dockerfile to reproduce:

FROM alpine:3.17
RUN apk add --update --no-cache git make gcc musl-dev autoconf automake
ARG CATATONIT_VERSION=99bb9048f532257f3a2c3856cfa19fe957ab6cec # v0.1.7+buildfix
RUN git clone https://github.com/openSUSE/catatonit.git /catatonit
WORKDIR /catatonit
RUN set -ex; \
	git checkout $CATATONIT_VERSION; \
	./autogen.sh; \
	cat -n configure | head -n3157; \
	./configure LDFLAGS="-static" --prefix=/ --bindir=/bin

configure fails to generate Makefile

Hi,
Running on 20.04.1-Ubuntu x86_64 GNU/Linux
sudo ./configure

returns

checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
./configure: line 2812: syntax error near unexpected token `2.4.2'
./configure: line 2812: `LT_PREREQ(2.4.2)'

thanks

Publish a container with catatonit in it for ease of copying into other containers?

I'm thinking something like:

FROM opensuse/catatonit:0.2.0 as init
FROM nodejs

ADD package.json /app
# ... blah blah blah

COPY --from=init /catatonit /catatonit
ENTRYPOINT ["/catatonit"]
CMD ["node", "app.js"]

That way it's readily available as a compiled static binary for use in containers without having to manage the download & compilation myself. I could make part of a multi-stage build do that for me, but I think it would be better to have that done once rather than everyone having to correctly get the right calls to gcc et all.

It would be also very awesome if that pre-made image was compiled for a bunch of different architectures, like arm64.

Is there a special reason for GPLv3+?

Is there is a special reason for the GPLv3 license? Or could re-licensing this project e.g. under GPLv2+ be considered?

The problem with GPLv3 is that users are not allowed to integrate Catatonit into products whose owner does not have the possibility to recompile Catatonit himself and replace it on the device. For example, in the case of a car, this results in a conflict of objectives: How can you certify the vehicle with software in such a way that you are allowed to drive it on the road, if you have to assume that the owner himself can change something in the software?

Since Linux containers are also becoming more and more important in the area of embedded devices, I think Catatonit would be even more valuable if users were also allowed to integrate it into products.

Actually a change of the license would perhaps still be possible. It would require the approval of all authors.

catatonit hangs when pid1 exits with code 127

Steps to reproduce:

$ CATATONIT_DEBUG=1 catatonit -- bash -c "exit 127"
DEBUG (catatonit:25051): pid1 (25052) spawned: bash
WARN (catatonit:25051): received SIGCHLD from pid1 (25052) but it's still alive
DEBUG (catatonit:25051): child process 25052 exited with code 127
DEBUG (catatonit:25051): got ECHILD: no children left to monitor

This one is completely reproducible. I found it by making a typo when trying to reproduce the other hanging issue (bash returns 127 for "Command not found"). Exit codes 126 and 128 work fine.

The WARN message makes it pretty clear what the control flow path is. I am not sure that the use of kill() is legitimate: the man page implies that a zombie process "exists" in the relevant sense for kill(pid,0) to succeed, so it may be that if neither WIFEXITED or WIFSIGNALED return true then it will always print the "it's still alive" message and hang. However, I do not know why the WIFEXITED macro would return false just because the exit code is 127!

Should catatonit rewrite LISTEN_PID?

podman (as per containers/podman#11316 at least) rewrites LISTEN_PID in socket-activated services to 1. However if using --init with catatonit this is not the right value, it should be 2. Its unclear if podman is responsible for making LISTEN_PID 2, or it catatonit should do the rewrite. However, no matter what podman does, it is safe for catatonit to rewrite LISTEN_PID=1.

Babysitter doesn't close fds

If using catatonit with e.g. podman to get a pid1 in a container that uses socket activation there is in an issue with how fd:s are handled. The fd:s are properly inherted into pid2, but they are not closed in the remaining pid1 babysitter process. This means if pid2 closes the inherited fd it is still kept open by pid1.

imho, pid1 should close all fds > 2 and dup the other ones to /dev/null (possibly excepting stderr).

autoreconf-2.71 fails due to duplicate AM_INIT_AUTOMAKE in configure.ac

On gentoo I have autoreconf-2.71 by default with which reconfiguring fails - Removing the second AM_INIT_AUTOMAKE at the end of configure.ac suffices to fix it.

Log:
autoreconf-2.71: export WARNINGS=
autoreconf-2.71: Entering directory '.'
autoreconf-2.71: configure.ac: not using Gettext
autoreconf-2.71: running: aclocal --force
configure.ac:34: error: AM_INIT_AUTOMAKE expanded multiple times
/usr/share/aclocal-1.16/init.m4:29: AM_INIT_AUTOMAKE is expanded from...
configure.ac:19: the top level
/usr/share/aclocal-1.16/init.m4:29: AM_INIT_AUTOMAKE is expanded from...
configure.ac:34: the top level
autom4te-2.71: error: /usr/bin/m4 failed with exit status: 1
aclocal-1.16: error: /usr/bin/autom4te-2.71 failed with exit status: 1
autoreconf-2.71: error: aclocal failed with exit status: 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.