more
is an ancient paging program dating back to the earliest unix operating system.
Lately, it was consuming 100% cpu while waiting for user input.
How can that be?
With more < long.txt
, top
reports:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 4705 user 20 0 230564 2636 2372 R 99.7 0.0 10:20.66 more
strace
reports more
repeated calling the poll
function:
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}, {fd=0, events=POLLIN|POLLERR|POLLHUP}, {fd=2, events=POLLIN|POLLERR|POLLHUP}], 3, -1) = 1 ([{fd=0, revents=POLLIN}])
more
is reading long.txt
on fd 0, or stdin:
poll
returns immediately, because there is always something to read from long.txt
, so this is the cause of the 100% cpu spin, a bugsignalfd
, to monitor things like terminal window size changesA comparison of more
on Fedora 39 strace
shows:
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}, {fd=0, events=POLLIN}], 2, -1) = 1 ([{fd=0, revents=POLLIN}]) read(2
Again, poll
returns immediately, because there is always something to read from long.txt
:
more
goes on to read from fd 2, and goes to sleep waiting for user inputread(2)
saves more
from spinning on Fedora 39, this means it is not paying attention to signals on fd 3What accounts for these bugs in such an ancient program?
more.c
and use the poll
system call resulted in signals being ignored while waiting
for the user to pagepoll
results in 100% cpu utilization