Hello!

Having some trouble with a rapid growing ~/.xsession-errors file,
especially after a pm-hibernate and resume, I'm quite sure that's
cpu.lua causing the mess.

First the errors of .xsession-errors (94MB):

:r!grep  "^error:" ~/xsession-errors.huge |sort|uniq -c

   7901 error: /home/jhd/.config/awesome/rc.lua:277: bad argument #4 to 
'format' (number expected, got string)
  47363 error: /home/jhd/.config/awesome/vicious/widgets/cpu.lua:35: bad 
argument #1 to 'lines' (/proc/stat: Too many open files)
   3638 error: /home/jhd/.config/awesome/vicious/widgets/mem.lua:24: bad 
argument #1 to 'lines' (/proc/meminfo: Too many open files)
 102549 error: /home/jhd/.config/awesome/vicious/widgets/net.lua:33: bad 
argument #1 to 'lines' (/proc/net/dev: Too many open files)
     80 error: /home/jhd/.config/awesome/vicious/widgets/pkg.lua:37: attempt to 
index local 'f' (a nil value)
     16 error: ...home/jhd/.config/awesome/vicious/widgets/weather.lua:42: 
attempt to index local 'f' (a nil value)

So I unregistered the widgets one by one:
# for all widgets: cpufreq, cputemp, netwidget, 
$ WIDGET=cpuwidget
$ echo "vicious.unregister($WIDGET, true)"|/usr/bin/awesome-client

Activated them again doing:
$ echo "vicious.activate($WIDGET)"|/usr/bin/awesome-client

Only the activated cpuwidget produces this '/proc/stat' file-handles:

jhd@case:~$ ls -l /proc/$(pidof awesome)/fd/
total 0
lr-x------ 1 jhd jhd 64 Dec 14 06:27 0 -> /dev/null
l-wx------ 1 jhd jhd 64 Dec 14 06:27 1 -> pipe:[13671408]
lr-x------ 1 jhd jhd 64 Dec 14 06:27 10 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 06:27 11 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 06:27 12 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 06:27 13 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 06:27 14 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 06:27 15 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 06:27 16 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 06:27 17 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 18 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 19 -> /proc/stat
l-wx------ 1 jhd jhd 64 Dec 14 06:27 2 -> pipe:[13671408]
lr-x------ 1 jhd jhd 64 Dec 14 08:36 20 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 21 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 22 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 23 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 24 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 25 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 26 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 27 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 28 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 29 -> /proc/stat
lrwx------ 1 jhd jhd 64 Dec 14 06:27 3 -> anon_inode:[eventpoll]
lr-x------ 1 jhd jhd 64 Dec 14 08:36 30 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 31 -> /proc/stat
lr-x------ 1 jhd jhd 64 Dec 14 08:36 32 -> /proc/stat
lrwx------ 1 jhd jhd 64 Dec 14 06:27 4 -> anon_inode:[eventfd]
lrwx------ 1 jhd jhd 64 Dec 14 06:27 5 -> socket:[15662851]
lrwx------ 1 jhd jhd 64 Dec 14 06:27 6 -> socket:[15663599]
l-wx------ 1 jhd jhd 64 Dec 14 06:27 7 -> pipe:[10299]
lrwx------ 1 jhd jhd 64 Dec 14 06:27 8 -> socket:[15664505]
lr-x------ 1 jhd jhd 64 Dec 14 06:27 9 -> pipe:[13670351]

Without the cpuwidget the output looks like this:
total 0
lr-x------ 1 jhd jhd 64 Dec 14 06:27 0 -> /dev/null
l-wx------ 1 jhd jhd 64 Dec 14 06:27 1 -> pipe:[13671408]
l-wx------ 1 jhd jhd 64 Dec 14 06:27 2 -> pipe:[13671408]
lrwx------ 1 jhd jhd 64 Dec 14 06:27 3 -> anon_inode:[eventpoll]
lrwx------ 1 jhd jhd 64 Dec 14 06:27 4 -> anon_inode:[eventfd]
lrwx------ 1 jhd jhd 64 Dec 14 06:27 5 -> socket:[15955336]
lrwx------ 1 jhd jhd 64 Dec 14 06:27 6 -> socket:[15953747]
l-wx------ 1 jhd jhd 64 Dec 14 06:27 7 -> pipe:[10299]
lrwx------ 1 jhd jhd 64 Dec 14 06:27 8 -> socket:[15952725]
lr-x------ 1 jhd jhd 64 Dec 14 06:27 9 -> pipe:[13670351]

The first thought was, after a suspend and resume the file-handle
changed, and the widget opens a new one and simply forget about the old
open handles. But, that's not the whole truth. You can see this behavior
of growing open file-handles doing this e.g. in a xterm (sry for the
long line):

$ watch -n 1 "echo -n 'total:      '; ls -l /proc/$(pidof awesome)/fd/|wc 
-l;echo  -n 'proc/stats: ';ls -l /proc/10415/fd/ |grep -c 'proc/stat';echo;ls 
-l  /proc/$(pidof awesome)/fd/"

You will get a lot of open file-handles if you register the widget like
this:
cpuwidget = awful.widget.graph()
[...]
vicious.register(cpuwidget, vicious.widgets.cpu, "$1", 0.5)
(BTW: caching doesn't help)

Or simply take '1' as the update-interval, it's nearly the same, and
you'll be sure not to run in any race-conditions.
.
After some time most of the open file-handles will leave (closed), but
some will stay - until you'll unregister the widget.

FYI; my ulimits:
:r!ulimit -aH
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) unlimited
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

There must be a bunch of open file-handles ...


Coming to the end, the attached patch fixes it for me. It doesn't trust
the lua garbage collector, instead of that, it will open the 'file'
/proc/stat, read the whole contents at once and closes the file immediately.
Now, there are no more stalling file-handles.

Regards
Juergen

>From 38f3ed0d77a200bfdbd6a2a9005ce11b7b6c3846 Mon Sep 17 00:00:00 2001
From: Juergen Descher <[email protected]>
Date: Fri, 14 Dec 2012 14:02:48 +0100
Subject: [PATCH] cpu: FIX: close opened file /proc/stat immediately

Fixes leaving opened files in /proc/$(pidof awesome)/fd/ under certain
circumstances, such as doing hiberte and resume often.

Signed-off-by: Juergen Descher <[email protected]>
---
 widgets/cpu.lua |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/widgets/cpu.lua b/widgets/cpu.lua
index 86a3e85..646a74f 100644
--- a/widgets/cpu.lua
+++ b/widgets/cpu.lua
@@ -7,7 +7,7 @@
 
 -- {{{ Grab environment
 local ipairs = ipairs
-local io = { lines = io.lines }
+local io = io
 local setmetatable = setmetatable
 local math = { floor = math.floor }
 local table = { insert = table.insert }
@@ -31,8 +31,16 @@ local cpu_active = {}
 local function worker(format)
     local cpu_lines = {}
 
+    local fd    -- file descriptor
+    local stats -- content
+
+    -- Read the file contents
+    fd = io.open("/proc/stat", "r")
+    stats = fd:read("*all")
+    fd:close()
+
     -- Get CPU stats
-    for line in io.lines("/proc/stat") do
+    for line in string.gmatch(stats,"[^\r\n]+") do
         if string.sub(line, 1, 3) ~= "cpu" then break end
 
         cpu_lines[#cpu_lines+1] = {}
-- 
1.7.10.4

Reply via email to