diff --git a/src/lua/console.lua b/src/lua/console.lua index 11fd8000f8312790ce48404b377860df759593c1..dc0541f68cd5fd6f39768facd3241eb1003ed996 100644 --- a/src/lua/console.lua +++ b/src/lua/console.lua @@ -24,19 +24,28 @@ local function format(status, ...) local function wrapnull(v) return v == nil and formatter.NULL or v end - if not status then - local v = ... - return formatter.encode({{error = wrapnull(v) }}) - end - local count = select('#', ...) - if count == 0 then - return "---\n...\n" - end - local res = {} - for i=1,count,1 do - table.insert(res, wrapnull(select(i, ...))) + local err + if status then + local count = select('#', ...) + if count == 0 then + return "---\n...\n" + end + local res = {} + for i=1,count,1 do + table.insert(res, wrapnull(select(i, ...))) + end + -- serializer can raise an exception + status, err = pcall(formatter.encode, res) + if status then + return err + else + err = 'console: an exception occurred during formatting result: '.. + tostring(err) + end + else + err = wrapnull(...) end - return formatter.encode(res) + return formatter.encode({{error = err }}) end -- diff --git a/test/app/console.result b/test/app/console.result index 40596ba7e469aa898ae91efc7b5cbc639a151dfa..0f603e15142dd99903dacadc7a93d2633947f2ca 100644 --- a/test/app/console.result +++ b/test/app/console.result @@ -1,5 +1,5 @@ TAP version 13 -1..26 +1..28 ok - console.listen started ok - Handshake ok - connect to console @@ -18,6 +18,8 @@ ok - remote eval ok - remote state.remote.host ok - remote state.remote.port ok - remote state.prompt +ok - exception handling +ok - exception handling ok - remote disconnect ok - console.listen stopped ok - console.listen uri support diff --git a/test/app/console.test.lua b/test/app/console.test.lua index 680edb14637870922a10bccd714db9e7ef81f4ed..483b3e4ecd4a0f196f92bedd76f167c8c37880f3 100755 --- a/test/app/console.test.lua +++ b/test/app/console.test.lua @@ -20,7 +20,7 @@ local EOL = "\n%.%.%.\n" test = tap.test("console") -test:plan(26) +test:plan(28) -- Start console and connect to it local server = console.listen(CONSOLE_SOCKET) @@ -98,6 +98,14 @@ test:is(state.remote.port, IPROTO_SOCKET, "remote state.remote.port") test:is(state.prompt, string.format("%s:%s", "unix/", IPROTO_SOCKET), "remote state.prompt") +-- Check exception handling (gh-643) +client:write("error('test')\n") +test:ok(yaml.decode(client:read(EOL))[1].error:match('test') ~= nil, + "exception handling") +client:write("setmetatable({}, { __serialize = function() error('test') end})\n") +test:ok(yaml.decode(client:read(EOL))[1].error:match('test') ~= nil, + "exception handling") + -- Disconnect from iproto client:write("~.\n") -- Check that iproto console has been disconnected