@@ -13,6 +13,9 @@ services:
- layersdb
build: .
image: halstead/layerindex-app
+ # "docker compose run" of update.py and the RRS tools: reap the
+ # bitbake servers that recipe parsing leaves behind
+ init: true
hostname: localhost
volumes:
- layersmeta:/opt/workdir
@@ -13,6 +13,9 @@ services:
- layersdb
build: .
image: halstead/layerindex-app
+ # "docker compose run" of update.py and the RRS tools: reap the
+ # bitbake servers that recipe parsing leaves behind
+ init: true
hostname: localhost
volumes:
- layersmeta:/opt/workdir
@@ -10,6 +10,9 @@ services:
- layersdb
build: .
image: halstead/layerindex-app
+ # "docker compose run" of update.py and the RRS tools: reap the
+ # bitbake servers that recipe parsing leaves behind
+ init: true
hostname: localhost
volumes:
- layersmeta:/opt/workdir
@@ -200,3 +200,20 @@ def test_compose_command(monkeypatch, result, expected):
assert calls == [['docker', 'compose', 'version']]
finally:
dockersetup.compose_command.cache_clear()
+
+
+@pytest.mark.parametrize('compose_file', ['docker-compose.yml', 'docker-compose.prod.yml',
+ 'docker-compose.staging.yml'])
+def test_compose_layersapp_has_init(compose_file):
+ # [YOCTO #16515] in "docker compose run --rm layersapp ..." the script is
+ # process 1; without an init process the bitbake servers started by
+ # recipe parsing stay as zombies until the container's process limit is hit
+ with open(os.path.join(basepath, compose_file)) as f:
+ services = yaml.safe_load(f)['services']
+ assert services['layersapp'].get('init') is True
+
+
+def test_compose_keeps_init(workdir):
+ dockersetup.edit_dockercompose('layers.example.com', '8080:80,8081:443', False)
+ services = load_compose(workdir)['services']
+ assert services['layersapp']['init'] is True
In "docker compose run --rm layersapp .../update.py", and likewise for the RRS tools, the script is process 1. Recipe parsing starts a bitbake server that outlives the parse, and with no init process to reap it, it stays as a zombie. A long run can then reach the container's process limit, after which every parse fails with "Resource temporarily unavailable". This happened to the RRS upgrade history on a test instance after about 3400 commits. Set "init: true" so that Docker's init reaps them; dockersetup.py copies the line unchanged. layerscelery doesn't need it: celery, as process 1, already reaps orphaned processes. [YOCTO #16515] AI-Generated: Claude Opus 5.5 Signed-off-by: Tim Orling <tim.orling@konsulko.com> --- docker-compose.prod.yml | 3 +++ docker-compose.staging.yml | 3 +++ docker-compose.yml | 3 +++ tests/test_dockersetup.py | 17 +++++++++++++++++ 4 files changed, 26 insertions(+)