Skip to content

sysv-initctl: avoid busy loop without FIFO clients - #1056

Closed
pva wants to merge 1 commit into
OpenRC:masterfrom
pva:fix-openrc-init-busy-loop
Closed

sysv-initctl: avoid busy loop without FIFO clients#1056
pva wants to merge 1 commit into
OpenRC:masterfrom
pva:fix-openrc-init-busy-loop

Conversation

@pva

@pva pva commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

sysv-initctl opened /run/initctl with O_RDONLY | O_NONBLOCK and called read() directly in a loop. Immediately after startup, no client has the FIFO open for writing, so read() returns zero instead of waiting. The daemon treated this as a short request and retried continuously, consuming CPU and flooding syslog with "read: short count".

This can be reproduced on a system using openrc-init by starting the compatibility daemon without connecting an initctl client:

rc-service sysv-initctl start
pid=$(pgrep -x sysv-initctl)
strace -p "$pid" -e read
top -p "$pid"

Before this change, strace repeatedly reports read() returning zero.

Open the read end nonblocking during setup, keep a dummy write end open, and then make the reader blocking. This allows the daemon to sleep in read() while no clients are connected. Mark both descriptors close-on-exec.

sysv-initctl opened /run/initctl with O_RDONLY | O_NONBLOCK and called
read() directly in a loop. Immediately after startup, no client has the
FIFO open for writing, so read() returns zero instead of waiting. The
daemon treated this as a short request and retried continuously,
consuming CPU and flooding syslog with "read: short count".

This can be reproduced on a system using openrc-init by starting the
compatibility daemon without connecting an initctl client:

    rc-service sysv-initctl start
    pid=$(pgrep -x sysv-initctl)
    strace -p "$pid" -e read
    top -p "$pid"

Before this change, strace repeatedly reports read() returning zero.

Open the read end nonblocking during setup, keep a dummy write end open,
and then make the reader blocking. This allows the daemon to sleep in
read() while no clients are connected. Mark both descriptors
close-on-exec.
@navi-desu navi-desu closed this in 53cf9bc Jul 31, 2026
@navi-desu

Copy link
Copy Markdown
Member

this is much of the same logic as openrc-init, so i pushed a commit reusing it

also there's no need to repeat the explanation every time, just refer to the old fix

@pva

pva commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@navi-desu Yea, it's a good idea to move code into a helper header. Yet, although the fixes are similar, the triggers are different. In the first case, the issue was triggered by connecting to the socket and sending a signal; here, it is triggered when no listener is present. That's why the descriptions were different.

@pva
pva deleted the fix-openrc-init-busy-loop branch July 31, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants