* * * * *
Just when I thought it was safe to run a gopher server
It appeared I had traded the problem of high CPU (Central Processing Unit)
usage [1] for a memory leak. Last night I saw:
-----[ data ]-----
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
gopher 31875 0.2 13.3 2174076 2171960 ttyp4 S+ Jun09 7:08 lua port70.lua /home/spc/gopher/config.lua
-----[ END OF LINE ]-----
(For the record—the VSZ (Virtual Size) and RSS (Resident Set Size) values are
the number of 4,096 byte blocks of memory for various reasons beyond the
scope of this post) and just before lunch today:
-----[ data ]-----
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
gopher 1572 0.2 11.1 1809672 1807644 ttyp4 S+ 04:30 1:07 lua port70.lua /home/spc/gopher/config.lua
-----[ END OF LINE ]-----
Not good. Especially when it's normally like:
-----[ data ]-----
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
gopher 20711 0.2 0.0 10588 9000 ttyp4 S+ 17:52 0:06 lua port70.lua /home/spc/gopher/config.lua
-----[ END OF LINE ]-----
And then there was this in the logs:
-----[ data ]-----
Jun 12 09:47:54 daemon err 71.19.142.20 gopher CRASH: coroutine thread: 0x8400404 dead: not enough memory
Jun 12 09:47:54 daemon err 71.19.142.20 gopher CRASH: thread: 0x8400404: stack traceback:
Jun 12 09:47:54 daemon err 71.19.142.20 gopher CRASH: thread: 0x8400404: [C]: in function 'org.conman.string.wrapt'
Jun 12 09:47:54 daemon err 71.19.142.20 gopher CRASH: thread: 0x8400404: ...e/lua/5.4/org/conman/app/port70/handlers/blog/format.lua:34: in upvalue 'wrap_text'
Jun 12 09:47:54 daemon err 71.19.142.20 gopher CRASH: thread: 0x8400404: ...e/lua/5.4/org/conman/app/port70/handlers/blog/format.lua:119: in upvalue 'run_flow'
Jun 12 09:47:54 daemon err 71.19.142.20 gopher CRASH: thread: 0x8400404: ...e/lua/5.4/org/conman/app/port70/handlers/blog/format.lua:598: in function 'org.conman.app.port70.handlers.blog.format'
Jun 12 09:47:54 daemon err 71.19.142.20 gopher CRASH: thread: 0x8400404: ...al/share/lua/5.4/org/conman/app/port70/handlers/blog.lua:227: in function <...al/share/lua/5.4/org/conman/app/port70/handlers/blog.lua:210>
Jun 12 09:47:54 daemon err 71.19.142.20 gopher CRASH: thread: 0x8400404: (...tail calls...)
Jun 12 09:47:54 daemon err 71.19.142.20 gopher CRASH: thread: 0x8400404: port70.lua:238: in function <port70.lua:205>
-----[ END OF LINE ]-----
Yeah, “not enough memory” while running the new C-based text wrapping
function [2]. I added a few checks to see if wrapt() wasn't updating the
character indicies correctly (and log if they weren't) then went for lunch.
Afterwards, I check and lo', memory was still growing, and none of the checks
I added had triggered.
Hmmm. Time to take down the gopher server and debug some code.
Sure enough, I found the one entry [3] that went off the rails. What followed
was a few hours of troubleshooting to find out why that one entry (and only
that entry) blows up. And it came down to a difference of semantics between
Lua and C (no, it had nothing to do with C's 0-based indexing and Lua's 1-
based indexing). Basically, the Lua code looked like:
-----[ Lua ]-----
local breakhere -- this is nil
..
if ctype == 'space' then
breakhere = i -- this is now an integer
...
end
if breakhere then
table.insert(result,s:sub(front,breakhere - 1))
...
end
breakhere = nil
-----[ END OF LINE ]-----
In Lua, only the values nil and false are considered “false”—a 0 value is
“true” in Lua. In C, any 0 value is considered “false.” I knew this when
translating the code, but it never occurred to me that a break point of a
line could be at the start of a line.
Until it was at the start of a line in that one entry—the code went into an
infinite loop trying to wrap text, thus causing the memory usage to consume
the computer.
Sigh.
It was easy enough to fix once the problem was diagnosed. And maybe now
things will get back to normal.
[1]
gopher://gopher.conman.org/0Phlog:2024/05/27.1
[2]
gopher://gopher.conman.org/0Phlog:2024/06/03.1
[3]
gopher://gopher.conman.org/0Phlog:2006/10/29.1
Email author at
[email protected]