You are not logged in.

#1 2011-11-16 17:38:12

ugugii
Member
Registered: 2009-06-06
Posts: 8

Memory Leakage in Conky with Lua

Hi there, I've been experiencing ongoing memory leakage using my Conky + Lua scripts. It tends to keep accumulating memory until I kill the process and restart it. Highest I've seen it go is 10% of my 4gb of RAM, so it does get to be substantial if unchecked.

I did google it, and it mentioned something about cairo_destroy(cr), so I inserted it at the end of functions randomly where it made sense (to my limited scripting skills) and where it didn't (just in case), but it didn't seem to make any difference.

Here is the lua script - it creates rings as % bars, I believe it was taken from somewhere on the arch forums months ago where it was also modified.

--[[
Ring Meters by londonali1010 (2009)
 
This script draws percentage meters as rings. It is fully customisable; all options are described in the script.
 
To call this script in Conky, use the following (assuming that you save this script to ~/scripts/rings.lua):
    lua_load ~/scripts/rings-v1.2.1.lua
    lua_draw_hook_pre ring_stats
 
]]

-- Background settings
corner_r=20
main_bg_colour=0x060606
main_bg_alpha=0.4
-- Ring color settings
ring_background_color = 0x000000
ring_background_alpha = 0.6
ring_foreground_color = 0x909090
ring_foreground_alpha = 1
-- Rings settings
settings_table = {
    {
        name='cpu',
        arg='cpu2',
        max=100,
        bg_colour=ring_background_color,
        bg_alpha=ring_background_alpha,
        fg_colour=ring_foreground_color,
        fg_alpha=ring_foreground_alpha,
        x=50, y=55,
        radius=31,
        thickness=3,
        start_angle=-180,
        end_angle=0
    },
    {
        name='cpu',
        arg='cpu1',
        max=100,
        bg_colour=ring_background_color,
        bg_alpha=ring_background_alpha,
        fg_colour=ring_foreground_color,
        fg_alpha=ring_foreground_alpha,
        x=50, y=55,
        radius=35,
        thickness=3,
        start_angle=-180,
        end_angle=0
    },
    {
        name='memperc',
        arg='',
        max=100,
        bg_colour=ring_background_color,
        bg_alpha=ring_background_alpha,
        fg_colour=ring_foreground_color,
        fg_alpha=ring_foreground_alpha,
        x=205, y=55,
        radius=32,
        thickness=10,
        start_angle=-180,
        end_angle=-0
    },
}



require 'cairo'

local function rgb_to_r_g_b(colour,alpha)
    return ((colour / 0x10000) % 0x100) / 255., ((colour / 0x100) % 0x100) / 255., (colour % 0x100) / 255., alpha
end

local function draw_ring(cr,t,pt)
    local w,h=conky_window.width,conky_window.height

    local xc,yc,ring_r,ring_w,sa,ea=pt['x'],pt['y'],pt['radius'],pt['thickness'],pt['start_angle'],pt['end_angle']
    local bgc, bga, fgc, fga=pt['bg_colour'], pt['bg_alpha'], pt['fg_colour'], pt['fg_alpha']

    local angle_0=sa*(2*math.pi/360)-math.pi/2
    local angle_f=ea*(2*math.pi/360)-math.pi/2
    local t_arc=t*(angle_f-angle_0)

    -- Draw background ring

    cairo_arc(cr,xc,yc,ring_r,angle_0,angle_f)
    cairo_set_source_rgba(cr,rgb_to_r_g_b(bgc,bga))
    cairo_set_line_width(cr,ring_w)
    cairo_stroke(cr)

    -- Draw indicator ring

    cairo_arc(cr,xc,yc,ring_r,angle_0,angle_0+t_arc)
    cairo_set_source_rgba(cr,rgb_to_r_g_b(fgc,fga))
    cairo_stroke(cr)
end

local function conky_ring_stats()
    local function setup_rings(cr,pt)
        local str=''
        local value=0

        str=string.format('${%s %s}',pt['name'],pt['arg'])
        str=conky_parse(str)

        value=tonumber(str)
        if value == nil then value = 0 end
        pct=value/pt['max']

        draw_ring(cr,pct,pt)
    end

    if conky_window==nil then return end
    local cs=cairo_xlib_surface_create(conky_window.display,conky_window.drawable,conky_window.visual, conky_window.width,conky_window.height)

    local cr=cairo_create(cs)

    local updates=conky_parse('${updates}')
    update_num=tonumber(updates)

    if update_num>1 then
        for i in pairs(settings_table) do
            setup_rings(cr,settings_table[i])
        end
    end
    cairo_destroy(cr)
end

--[[ This is a script made for draw a transaprent background for conky ]]

local function conky_draw_bg()
    if conky_window==nil then return end
    local w=conky_window.width
    local h=conky_window.height
    local cs=cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, w, h)
    local cr=cairo_create(cs)
--    local thick=2

    cairo_move_to(cr,corner_r,0)
    cairo_line_to(cr,w-corner_r,0)
    cairo_curve_to(cr,w,0,w,0,w,corner_r)
    cairo_line_to(cr,w,h-corner_r)
    cairo_curve_to(cr,w,h,w,h,w-corner_r,h)
    cairo_line_to(cr,corner_r,h)
    cairo_curve_to(cr,0,h,0,h,0,h-corner_r)
    cairo_line_to(cr,0,corner_r)
    cairo_curve_to(cr,0,0,0,0,corner_r,0)
    cairo_close_path(cr)

    cairo_set_source_rgba(cr,rgb_to_r_g_b(main_bg_colour,main_bg_alpha))
    --cairo_set_line_width(cr,thick)
    --cairo_stroke(cr)
    cairo_fill(cr)
    cairo_destroy(cr)
end

function conky_main()
    conky_draw_bg()
    conky_ring_stats()
    cairo_destroy(cr)
end

And this is called into conky via:

background no
override_utf8_locale no

use_xft yes
xftfont Monospace:size=8
## orig font cure
text_buffer_size 2048
update_interval 1.0
total_run_times 0

own_window yes
own_window_transparent yes
own_window_type desktop
own_window_colour 191919
own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager
double_buffer yes

minimum_size  600 90
maximum_width 320

draw_shades no
draw_outline no
draw_borders no
draw_graph_borders no

default_color 909090
default_shade_color fed053
default_outline_color 7f8f9f

alignment br
gap_x 30
gap_y 50

no_buffers yes
uppercase no
cpu_avg_samples 2
override_utf8_locale no

color1 fff

border_inner_margin 5
border_outer_margin 5

own_window_argb_visual no
own_window_argb_value 200

lua_load ~/.conky/rings.lua
lua_draw_hook_pre main

Left out the conky TEXT section unless anybody desperately needs to see that too.

If anybody can point me in the right direction with this silly thing, that would be appreciated. Thanks!

Last edited by ugugii (2011-11-16 17:42:00)

Offline

#2 2011-11-17 14:31:39

juster
Forum Fellow
Registered: 2008-10-07
Posts: 195

Re: Memory Leakage in Conky with Lua

I don't know much about cairo or conky but you call cairo_xlib_surface_create twice each loop and never call cairo_surface_destroy. There is also a cairo_destroy call in the main function that looks out of place.

Offline

#3 2011-11-19 04:40:51

ugugii
Member
Registered: 2009-06-06
Posts: 8

Re: Memory Leakage in Conky with Lua

function conky_main()
    conky_draw_bg()
    conky_ring_stats()
    cairo_destroy(cr)
    cairo_surface_destroy(cr)
end

Is that what you meant? The separate cairo_xlib_surface_create calls are for the rings and the backgrounds which seem to be triggered separately.
I removed one of the cairo_destroy calls (the one right at the end of the local function conky_ring_stats() portion) and added in the cairo_surface_destroy(cr) and now it seems to be bloating even faster. sad

edit: currently trying cairo_surface_destroy() to see if that makes a difference.

edit2: no, it does not. I'm now stumped.

Last edited by ugugii (2011-11-19 16:19:18)

Offline

#4 2011-11-20 04:34:14

juster
Forum Fellow
Registered: 2008-10-07
Posts: 195

Re: Memory Leakage in Conky with Lua

No I meant that the destroy functions should not be in conky_main at all. Why? Because you are using cr as an argument when you have no local cr defined. You are passing the undefined value (nil) to these destroy functions and they do nothing.

Like I said, I don't use conky or cairo but it is generally a good idea to destroy a resource you create. If you don't you will get memory leaks because "creating" is usually vague language that comes down to allocating memory and "destroy" deallocates memory.

This line from your own post creates a surface and stores it in the cs variable:

local cs=cairo_xlib_surface_create(conky_window.display,conky_window.drawable,conky_window.visual, conky_window.width,conky_window.height)

Yet you forget to deallocate the surface stored in cs. So add a line like this after each cairo_destroy(cr):

cairo_surface_destroy(cs)

I hope that helps.

Offline

#5 2011-11-20 06:08:27

fsckd
Forum Fellow
Registered: 2009-06-15
Posts: 4,173

Re: Memory Leakage in Conky with Lua

You are an inspiration to millions.</Oprah>

I added as,

local cs=cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, w, h)
cr=cairo_create(cs)
cairo_surface_destroy(cs)

and

<snip>
cairo_set_source_rgba(cr,rgb_to_r_g_b(bg_colour,bg_alpha))
cairo_fill(cr)

cairo_destroy(cr)

I destroyed cs as soon as cr is created as cs is no longer needed thereafter. cr is needed for the rest of the function and is deleted at the end.

No more memory leaks (or reduced to very, very small leaks). big_smile

Full code: http://sprunge.us/EbTV.


aur S & M :: forum rules :: Community Ethos
Resources for Women, POC, LGBT*, and allies

Offline

#6 2011-12-11 14:09:39

ugugii
Member
Registered: 2009-06-06
Posts: 8

Re: Memory Leakage in Conky with Lua

Apologies for the delayed response, just got back from a backpacking trip.

Anyways, tried out your suggestions guys, worked like a charm!

*Hat tip to the good sirs*


edit: actually, after leaving it on for about 2.5 days, it's now at 3.03%. So it's still leaking, but at a muchly reduced rate than it was before. So now it's somewhat mildly irritating rather than becoming a RAM black hole. Oh well.

Last edited by ugugii (2011-12-13 09:08:44)

Offline

Board footer

Powered by FluxBB