wibox: Fix __to_string and garbage collection.
There was no "real" unsolvable GC issues, but at least for Lua 5.2 and 5.3, it wasn't possible to GC a wibox anymore. This commit unwind the circular references with 3 new weak refs. This is enough to get a specific test to pass on Lua 5.3. It's voodoo, but this was actually a pretty bad leak. There's other according to some test I wrote, but that's one. As for to_string, it appears to be accidental refactoring oversight.
This commit is contained in:
parent
9a3b6fe2a2
commit
16b92a0614
|
@ -55,6 +55,10 @@ local function get_widget_context(self)
|
||||||
for k, v in pairs(self._widget_context_skeleton) do
|
for k, v in pairs(self._widget_context_skeleton) do
|
||||||
context[k] = v
|
context[k] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Set the metatable to give access to the weak wibox.
|
||||||
|
setmetatable(context, getmetatable(self._widget_context_skeleton))
|
||||||
|
|
||||||
self._widget_context = context
|
self._widget_context = context
|
||||||
|
|
||||||
-- Give widgets a chance to react to the new context
|
-- Give widgets a chance to react to the new context
|
||||||
|
|
|
@ -254,7 +254,10 @@ local function setup_signals(w)
|
||||||
local function clone_signal(name)
|
local function clone_signal(name)
|
||||||
-- When "name" is emitted on wibox.drawin, also emit it on wibox
|
-- When "name" is emitted on wibox.drawin, also emit it on wibox
|
||||||
obj:connect_signal(name, function(_, ...)
|
obj:connect_signal(name, function(_, ...)
|
||||||
w:emit_signal(name, ...)
|
local wb = obj.get_wibox()
|
||||||
|
if wb then
|
||||||
|
wb:emit_signal(name, ...)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -296,16 +299,30 @@ local function new(args)
|
||||||
local ret = object()
|
local ret = object()
|
||||||
local w = capi.drawin(args)
|
local w = capi.drawin(args)
|
||||||
|
|
||||||
|
local weak_wibox = setmetatable({ret}, {__mode = "v"})
|
||||||
|
|
||||||
|
-- Strong ref
|
||||||
function w.get_wibox()
|
function w.get_wibox()
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
ret.drawin = w
|
ret.drawin = w
|
||||||
ret._drawable = wibox.drawable(w.drawable, { wibox = ret },
|
|
||||||
|
-- Do not pass a strong reference to the wibox, it will confuse the GC.
|
||||||
|
local context_skeleton = setmetatable({}, {
|
||||||
|
__index = function(_, key)
|
||||||
|
if key == "wibox" then return weak_wibox[1] end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
ret._drawable = wibox.drawable(w.drawable, context_skeleton,
|
||||||
"wibox drawable (" .. object.modulename(3) .. ")")
|
"wibox drawable (" .. object.modulename(3) .. ")")
|
||||||
|
|
||||||
|
-- Weak ref
|
||||||
function ret._drawable.get_wibox()
|
function ret._drawable.get_wibox()
|
||||||
return ret
|
return weak_wibox[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
ret._drawable:_inform_visible(w.visible)
|
ret._drawable:_inform_visible(w.visible)
|
||||||
|
@ -328,13 +345,7 @@ local function new(args)
|
||||||
ret:set_fg(args.fg or beautiful.fg_normal)
|
ret:set_fg(args.fg or beautiful.fg_normal)
|
||||||
|
|
||||||
-- Add __tostring method to metatable.
|
-- Add __tostring method to metatable.
|
||||||
local mt = {}
|
|
||||||
local orig_string = tostring(ret)
|
local orig_string = tostring(ret)
|
||||||
mt.__tostring = function()
|
|
||||||
return string.format("wibox: %s (%s)",
|
|
||||||
tostring(ret._drawable), orig_string)
|
|
||||||
end
|
|
||||||
ret = setmetatable(ret, mt)
|
|
||||||
|
|
||||||
-- Make sure the wibox is drawn at least once
|
-- Make sure the wibox is drawn at least once
|
||||||
ret.draw()
|
ret.draw()
|
||||||
|
@ -359,6 +370,10 @@ local function new(args)
|
||||||
else
|
else
|
||||||
rawset(self, k, v)
|
rawset(self, k, v)
|
||||||
end
|
end
|
||||||
|
end,
|
||||||
|
__tostring = function()
|
||||||
|
return string.format("wibox: %s (%s)",
|
||||||
|
tostring(ret._drawable), orig_string)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue