Skip to content

Commit

Permalink
Avoid reentrance when in printReplacement
Browse files Browse the repository at this point in the history
hs.ipc replaces the print function with one that calls the original,
but also sends anything that print prints to any of the remote
connections. If you have debugging enabled, that means that the moment
the remote connection is created, a bunch of print statements are sent
to the this connection.

The problem I had is that my use of hs (command) was simply to send a
message to the screen:

     warning () {
        hs -c "hs.alert.show('$1')" > /dev/null
        echo "$1"
     }

The connection was so ephemeral, than I frequently got errors (related
to the client no long existing) which were tried to be send to the
client... so I ended with the following messages:

   2023-12-31 22:00:02: 22:00:02 ERROR: LuaSkin: hs.ipc callback is
   being called recursively. Check your callback function, it is
   triggering further IPC messages. This message was triggered after
   reaching 5 recursive callbacks.

This code avoid recursion for the same IPC client by keeping a counter
of how many times the client has entered the critical region.
  • Loading branch information
gitmsr authored and cmsj committed Nov 30, 2024
1 parent 251f5af commit 6edc619
Showing 1 changed file with 35 additions and 2 deletions.
37 changes: 35 additions & 2 deletions extensions/ipc/ipc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,52 @@ local MSG_ID = {
CONSOLE = 3, -- cloned console output
}

-- avoid printReplacement to be reentrant
-- otherwise errors might cascade into lots of recursive prints
module.insidePrintInstances = {}

module.print_enter = function(instance)
val = module.insidePrintInstances[instance] or 0
module.insidePrintInstances[instance] = val + 1
end

module.print_exit = function(instance)
-- make sure instance exists
if module.insidePrintInstances[instance] then
module.insidePrintInstances[instance] = module.insidePrintInstances[instance] - 1
if module.insidePrintInstances[instance] == 0 then
module.insidePrintInstances[instance] = nil
end
end
end

module.print_inside = function(instance)
val = module.insidePrintInstances[instance]
return val and val > 0
end

local originalPrint = print
local printReplacement = function(...)
originalPrint(...)
for _,v in pairs(module.__registeredCLIInstances) do
for i,v in pairs(module.__registeredCLIInstances) do
originalPrint(string.format("to print instance [%s]", i))
if v._cli.console and v.print and not v._cli.quietMode then
-- v.print(...)
-- make it more obvious what is console output versus the command line's

if module.print_inside(i) then
originalPrint(string.format("Instance of [%s] already recursing [%d] times, do not do ",
i, module.insidePrintInstances[i]))
else
module.print_enter(i)
local things = table.pack(...)
local stdout = (things.n > 0) and tostring(things[1]) or ""
for i = 2, things.n do
stdout = stdout .. "\t" .. tostring(things[i])
stdout = stdout .. "\t" .. tostring(things[i])
end
v._cli.remote:sendMessage(stdout .. "\n", MSG_ID.CONSOLE)
module.print_exit(i)
end
end
end
end
Expand Down

0 comments on commit 6edc619

Please sign in to comment.