Closed mirtlecn closed 6 months ago
檢查 整個方案中有無 leveldb 實例,且已 loaded ( 可以使用 :close() 關閉, 但可能再也開不起來了,因爲 user_dict 調用 db 是常開狀態 )
如果有和 方案中是否有衝突 上次討論中有使用 lua 環境製造 dbpool 的腳本 ,要取消 或是 用 :close() 全關閉.
確保 lua 環境中 所有 leveldb 實例中 與 user_dict 衝突
還是一個原則 儘量不要用 leveldb 開啓 user_dict 的db
fcitx5-rime 似乎不会将错误写入 log,可能需要一些额外的操作。因此我选了 ibus-rime 测试
不知道你能否复现?
rime/home 有一个 issue 看 log 似乎也与此相关:
我觉得它是 bug 的原因是:
你可以先將 更新的 expent_translator.lua 重新下載 試試 commits --> commit 變數名 錯誤 這個錯誤 只會造成 callback 呼叫 失敗 沒有無法開啓userdict 的問題
我没有用那个 lua,整个方案只用了一个测试 lua,就是上面写的那个。
如若诸位维护者有空,请确认此 issue 是否存在,或者给予指导。
个人已经在两台虚拟机的 fcitx5-rime 和 ibus-rime 稳定复现,且鼠须管、fcitx5 android 也有相关报错。rime/home 的一则 issue 据我判断也可能与此有关。
简易的测试方案和 lau 已经在主贴中提供。
@hchunhui @TsinamLeung (为当初引入该对象的贡献者)
感激不尽。
原因是此问题会影响多个前端,导致前端无法继续同步,且报错不指向 lua 错误而是指向用户词典被锁定。
如若诸位维护者有空,请确认此 issue 是否存在,或者给予指导。
个人已经在两台虚拟机的 fcitx5-rime 和 ibus-rime 稳定复现,且鼠须管、fcitx5 android 也有相关报错。rime/home 的一则 issue 据我判断也可能与此有关。
简易的测试方案和 lau 已经在主贴中提供。
@hchunhui @TsinamLeung (为当初引入该对象的贡献者)
感激不尽。
原因是此问题会影响多个前端,导致前端无法继续同步,且报错不指向 lua 错误而是指向用户词典被锁定。
我目前工作電腦還沒有測試還境,因此我見到你的Code我猜想是: 如果Memory沒有被回收則會佔用leveldb。 透過觀察前端的implementation,可以見到是rime_api的sync_user_data作全部同步操作的
RIME_API Bool RimeSyncUserData() {
RimeCleanupAllSessions();
Deployer& deployer(Service::instance().deployer());
deployer.ScheduleTask("installation_update");
deployer.ScheduleTask("backup_config_files");
deployer.ScheduleTask("user_dict_sync");
return Bool(deployer.StartMaintenance());
}
RIME_API void RimeCleanupAllSessions() {
Service::instance().CleanupAllSessions();
}
void Service::CleanupAllSessions() {
sessions_.clear();
}
// SessionMap session_
// using SessionMap = map<SessionId, an<Session>>;
此步似乎是notify to release session.(這個操作應把Memory全部清空) 我認為短期解決方案是: 在每次F.func 中新建Memory實例,確保在function結束後能被Release(可能會導致效能下降)
之後可能需要lua component能夠捕獲到session deconstructing時的訊息,並傳遞給各Lua部件,調起sessionDestory的handler(需要用戶自行編寫) 這樣做的目的是因為,luaComponent是隨着librime加載而initialize的,僅當librime 關閉時,lua 的 context才會清空。因此需要自行管理自librime取得的組件
在每次F.func 中新建Memory實例,確保在function結束後能被Release
感谢指导,我会测试并给予反馈
我已经测试并更新到主 issue,在 func 函数中使用 local foo = Memory 新建一个对象也会报错。
唯一不报错的,是在 init 函数中,用 local foo = Memory 新建一个对象。
在關閉 section 時 lua component 也會解構 LuaObj env 也會移除 可以試試 在 LuaMemory LuaTranslator .... 有 Lua member 解構時 加上lua->gc();
所有 關於 librime 物件 都要掛在 env 中 ,不能掛到 upvalue or global
--module file
local F={}
local m_mem
g_mem=nil
function F.init(env)
env.mem = Memory(.....)
F.mem = env.mem -- NG
m_mem = env.mem -- NG
g_mem = env.mem -- NG
end
function F.func(inp, env)
local mem = env.mem -- ok
end
在關閉 section 時 lua component 也會解構 LuaObj env 也會移除 可以試試 在 LuaMemory LuaTranslator .... 有 Lua member 解構時 加上lua->gc();
所有 關於 librime 物件 都要掛在 env 中 ,不能掛到 upvalue or global
--module file local F={} local m_mem g_mem=nil function F.init(env) env.mem = Memory(.....) F.mem = env.mem -- NG m_mem = env.mem -- NG g_mem = env.mem -- NG end function F.func(inp, env) local mem = env.mem -- ok end
-- filter:
-- - lua_fiter@*test
local F = {}
function F.init( env )
-- local foo = Memory( env.engine, env.engine.schema) -- no error
-- env.foo = Memory( env.engine, env.engine.schema) -- error
end
function F.func( input, env )
local foo = Memory( env.engine, env.engine.schema) -- error
-- env.foo = Memory( env.engine, env.engine.schema) -- error
for cand in input:iter() do
cand.comment = '*' -- make sure this lua being called
yield( cand )
end
end
return F
加上個 試試,在同步時 蜀發 engine 解構 lua_component 完成 fini 後 gc()
Memory Component.Translator Processor .....
要掛在 env
git apply patch
diff --git a/src/lua_gears.cc b/src/lua_gears.cc
index 9e1f704..0f8a01e 100644
--- a/src/lua_gears.cc
+++ b/src/lua_gears.cc
@@ -159,6 +159,7 @@ LuaFilter::~LuaFilter() {
LOG(ERROR) << "LuaFilter::~LuaFilter of "<< name_space_ << " error(" << e.status << "): " << e.e;
}
}
+ lua_->gc();
}
//--- LuaTranslator
@@ -186,6 +187,7 @@ LuaTranslator::~LuaTranslator() {
LOG(ERROR) << "LuaTranslator::~LuaTranslator of "<< name_space_ << " error(" << e.status << "): " << e.e;
}
}
+ lua_->gc();
}
//--- LuaSegmentor
@@ -213,6 +215,7 @@ LuaSegmentor::~LuaSegmentor() {
LOG(ERROR) << "LuaSegmentor::~LuaSegmentor of "<< name_space_ << " error(" << e.status << "): " << e.e;
}
}
+ lua_->gc();
}
//--- LuaProcessor
@@ -244,6 +247,7 @@ LuaProcessor::~LuaProcessor() {
LOG(ERROR) << "LuaProcessor::~LuaProcessor of "<< name_space_ << " error(" << e.status << "): " << e.e;
}
}
+ lua_->gc();
}
} // namespace rime
在關閉 section 時 lua component 也會解構 LuaObj env 也會移除 可以試試 在 LuaMemory LuaTranslator .... 有 Lua member 解構時 加上lua->gc(); 所有 關於 librime 物件 都要掛在 env 中 ,不能掛到 upvalue or global
--module file local F={} local m_mem g_mem=nil function F.init(env) env.mem = Memory(.....) F.mem = env.mem -- NG m_mem = env.mem -- NG g_mem = env.mem -- NG end function F.func(inp, env) local mem = env.mem -- ok end
-- filter: -- - lua_fiter@*test local F = {} function F.init( env ) -- local foo = Memory( env.engine, env.engine.schema) -- no error -- env.foo = Memory( env.engine, env.engine.schema) -- error end function F.func( input, env ) local foo = Memory( env.engine, env.engine.schema) -- error -- env.foo = Memory( env.engine, env.engine.schema) -- error for cand in input:iter() do cand.comment = '*' -- make sure this lua being called yield( cand ) end end return F
Memory 中有 OnCommit(ctx) 掛在 translation 中 怪怪的
function F.fini(env)
env.mem=nil
collectgarbage('collect')
end
不好意思,改源码然后编译测试,我暂时没这个条件,虚拟机里面编译 boost 和 librime 很慢,会卡死。
主机是 Weasel,倒是能编译,但它不报这个错误。
function F.fini(env)
env.mem=nil
collectgarbage('collect')
end
这个我试试,之后反馈给你。不过我认为没有帮助,因为你看
在 func 函数内用 local foo = memory 的方式仍然会引起 leveldb 被锁定,不像是因为没有回收资源造成的错误
lifetime env 底下的 一定大於 func 下的 local var
在 func 中 local mem 參考 env.mem 執行完 回收 mem
func(inp,env)
local mem = env.mem
end -- distory mem [point to env.mem]
lifetime env 底下的 一定大於 func 下的 local var
在 func 中 local mem 參考 env.mem 執行完 回收 mem func(inp,env) local mem = env.mem end -- distory mem [point to env.mem]
赋值 nil 并 collectgarbage('collect') 不会导致同步错误!
当前测试了 ibus-rime 是成功解决了问题。其他的还没测试,
@shewer
local F = {}
function F.init( env )
env.mem = Memory( env.engine, env.engine.schema)
end
function F.func( input, env )
for cand in input:iter() do
cand.comment = '-' -- test if this lua has been called
yield( cand )
end
end
function F.fini(env)
env.mem=nil
collectgarbage('collect')
end
return F
fcitx5-rime 测试也没有问题。
这样做了后,直接 update_user_dict 也不会有问题了。
想问下,我想保持对 librime 之前版本的兼容,希望直接在 fini 函数里面,手动回收 Memory,如之前的代码所示,应当没有负面效果吧?此操作不会在用户输入的情况下因回收资源而造成卡顿吧?
影響不大 , 只發生在 session close () 還有更頻繁的 LuaTranslation
依赖gc释放内存以外的资源并不是很合理,因为gc的时机本来就是不确定的。最好是能给 Memory
加一个 close()
或 release()
之类的方法,在 fini()
里面手动确保释放掉它打开的词典。
根據上述狀況 ComponentReg 可能也有問題 , table_translator script_translator 也是屬於 Memory 類
Memory 成員有 字典(unique_ptr) 和 notifier 要如何解構 自己? env.mem:close() ?
原來的想法是 env (LuaObj) 在消滅時 env 下面的 userdata 就可以被回收了,所以在此時觸發一次 gc()
But never rely on GC if so it must be our mechanism
Get Outlook for Androidhttps://aka.ms/AAb9ysg
From: Shewer Lu @.> Sent: Sunday, May 12, 2024 11:11:19 AM To: hchunhui/librime-lua @.> Cc: Chiram @.>; Mention @.> Subject: Re: [hchunhui/librime-lua] 【Bug】Memory 对象会导致 Rime 无法同步 (Issue #335)
根鲜�r ComponentReg 可能也有} , table_translator script_translator 也是凫 Memory
Memory 成T有 字典(unique_ptr) 和 notifier 要如何解 自己? env.mem:close() ?
原淼南敕ㄊ env (LuaObj) 在消r env 下面的 userdata 就可以被回收了,所以在此r|l一次 gc()
― Reply to this email directly, view it on GitHubhttps://github.com/hchunhui/librime-lua/issues/335#issuecomment-2106101629, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AKU7ZT55IGWGCDCFH2IEPP3ZB3MVPAVCNFSM6AAAAABHHMEWIGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMBWGEYDCNRSHE. You are receiving this because you were mentioned.Message ID: @.***>
如 #330 所示
Memory 无法用于已经启用,且用户词典打开(默认情况)的方案,会导致大部分前端同步时抛出词典锁定的错误。
而如果想要使用 Memory 对象,所用方案很可能为启用用户词典状态(默认),lua 并未阻止此危险操作。所以此设计似有问题。请确认。
复现
测试方案(内含报错信息):
test_lua.zip
有关问题的前端:ibus-rime,Squirrel ,fcitx5-rime(不会显示错误,但无法继续同步)
预期情况
Memory 可以正常工作,不导致用户词典锁定。
或者以下情况均可:
问题 lua
Originally posted by @mirtlecn in https://github.com/hchunhui/librime-lua/issues/333#issuecomment-2094575070