Introduction

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?

Spinning the CPU

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 bug
  • fd 3 came from signalfd, to monitor things like terminal window size changes
  • fd 2 is for reading user commands, such as paging

A 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:

  • However, more goes on to read from fd 2, and goes to sleep waiting for user input
  • While read(2) saves more from spinning on Fedora 39, this means it is not paying attention to signals on fd 3
  • This is also a bug

Conclusion

What accounts for these bugs in such an ancient program?

  • more.c tells the story
  • A 2020 exercise to modernize more.c and use the poll system call resulted in signals being ignored while waiting for the user to page
  • A 2024 attempt to move fd 2 into poll results in 100% cpu utilization
  • Ironically, this bug is hardly noticeable in today's multicore cpus, unless, you notice a slight increase in fan speed
Last updated on 15 Aug 2025
133, New Bridge Road #24-01
Chinatown Point S(049513) •
Tel: 6-552-6826 •
Email: sales@bumblebee.com.sg
Copyright Bumble Bee Laboratories Pte. Ltd. March 2025