Problem
BarcodeBuddy fails intermittently with "Could not connect to Grocy server" in rootless Docker environments due to zombie process accumulation exhausting PID limits.
Impact: Breaks after ~70 scans (1-2 days of use)
Cause: 2 zombie processes created per barcode scan
Evidence
Application Errors
2025-11-12 06:28:22: Could not connect to Grocy server: Could not lookup Grocy barcodes
This is probably due to no process being available for the simple curl or DNS lookup of grocy-url/api/
Kernel Logs
$ dmesg -T | grep fork
cgroup: fork rejected by pids controller
Zombie Accumulation
$ docker top barcodebuddy | grep defunct
299 1 Zs [screen] <defunct>
302 1 Zs [php] <defunct>
389 1 Zs [screen] <defunct>
391 1 Zs [php] <defunct>
477 1 Zs [screen] <defunct>
479 1 Zs [php] <defunct>
566 1 Zs [screen] <defunct>
568 1 Zs [php] <defunct>
After 4 scans: 8 zombies (2 per scan: screen + php)
All zombies have PPID=1 (not being reaped by supervisor)
PID Exhaustion
$ cat /sys/fs/cgroup/.../pids.current
170
$ cat /sys/fs/cgroup/.../pids.max
171
Container at capacity → fork() fails → DNS resolution fails → Grocy API unreachable
Why Only Rootless Docker?
| Docker Mode |
PID Limit |
Result |
| Rootful |
4,194,304 |
Bug hidden (would take years) |
| Rootless |
~171 (systemd limit) |
Breaks in 1-2 days |
This was the case on a raspberry pi zero 2.
Suspected Source
File: example/grabInput.sh line 151
sudo -H -u $WWW_USER /usr/bin/screen -dm /usr/bin/php "$SCRIPT_LOCATION" $enteredText
The screen -dm spawns detached processes that become zombies when they exit. Pattern matches exactly: 2 zombies per scan (screen + php), both PPID=1.
Potential fix: Using & instead of screen -dm might resolve this, as the parent process could then properly reap the child when it exits:
sudo -H -u $WWW_USER /usr/bin/php "$SCRIPT_LOCATION" $enteredText &
Verification Steps
Check for zombies:
docker top barcodebuddy | grep defunct | wc -l
Monitor PID growth:
watch 'docker stats --no-stream barcodebuddy --format "PIDs: {{.PIDs}}"'
PIDs should stay constant (~30). If growing by 2 per scan → zombie leak confirmed.
Temporary Workaround
For rootless Docker users experiencing this:
Increase PID limits:
# /etc/systemd/system/user-.slice.d/override.conf
[Slice]
TasksMax=2048
# docker-compose.yml
services:
barcodebuddy:
pids_limit: 750
Auto-restart to clear zombies:
# Timer to restart every 2 days
# /etc/systemd/system/barcodebuddy-restart.timer
[Timer]
OnCalendar=*-*-1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31 02:00:00
This buys time but doesn't fix root cause.
Environment: Rootless Docker, systemd with TasksMax limits, cgroups v2
Reproducibility: 100% in rootless Docker with PID constraints
Affected Repos: Forceu/barcodebuddy (grabInput.sh), forceu/barcodebuddy-docker (uses script)
Problem
BarcodeBuddy fails intermittently with "Could not connect to Grocy server" in rootless Docker environments due to zombie process accumulation exhausting PID limits.
Impact: Breaks after ~70 scans (1-2 days of use)
Cause: 2 zombie processes created per barcode scan
Evidence
Application Errors
This is probably due to no process being available for the simple curl or DNS lookup of grocy-url/api/
Kernel Logs
$ dmesg -T | grep fork cgroup: fork rejected by pids controllerZombie Accumulation
PID Exhaustion
Container at capacity → fork() fails → DNS resolution fails → Grocy API unreachable
Why Only Rootless Docker?
This was the case on a raspberry pi zero 2.
Suspected Source
File:
example/grabInput.shline 151The
screen -dmspawns detached processes that become zombies when they exit. Pattern matches exactly: 2 zombies per scan (screen + php), both PPID=1.Potential fix: Using
&instead ofscreen -dmmight resolve this, as the parent process could then properly reap the child when it exits:Verification Steps
Check for zombies:
Monitor PID growth:
watch 'docker stats --no-stream barcodebuddy --format "PIDs: {{.PIDs}}"'PIDs should stay constant (~30). If growing by 2 per scan → zombie leak confirmed.
Temporary Workaround
For rootless Docker users experiencing this:
Increase PID limits:
# /etc/systemd/system/user-.slice.d/override.conf [Slice] TasksMax=2048Auto-restart to clear zombies:
This buys time but doesn't fix root cause.
Environment: Rootless Docker, systemd with TasksMax limits, cgroups v2
Reproducibility: 100% in rootless Docker with PID constraints
Affected Repos:
Forceu/barcodebuddy(grabInput.sh),forceu/barcodebuddy-docker(uses script)