I was working on a script when I realised that after ~50 to 60 keys, no further input is received. While searching Google, I came across #317, which seems to be what is happening to me. Any suggestions for how to avoid this?
@lazandrei19 how are you storing your eventtap object?
The current eventtap code detects when Apple disables the eventtap and re-enables it...
if ((type == kCGEventTapDisabledByTimeout) || (type == kCGEventTapDisabledByUserInput)) {
[skin logBreadcrumb:[NSString stringWithFormat:@"eventtap restarted: (%d)", type]] ;
CGEventTapEnable(e->tap, true);
return event ;
}
The logBreadcrumb method does log this via Crashlog, but not where you can get to it from Hammerspoon, so if you want to verify if this is occurring, you'll need to add hs.crash.crashLogToNSLog(true) to your init.lua file and then open up the Apple Console application and watch for the message.
As @cmsj alludes to, if your eventtap object is not being stored in a global variable or in a local variable that is being referenced by something that is ultimately referenced by a global variable, Lua's own garbage collection could be shutting it down and that won't be logged... You could add something like the following to your init.lua to detect if that is occurring (I use a variant of this when debugging new modules and need to know if/when they get collected):
-- __originalEventTapGC can be local because it is referenced by the new __gc function stored
-- in the metatable for hs.eventtap -- this "loop" prevents Lua from garbage collecting it away
local __originalEventTapGC = hs.getObjectMetatable("hs.eventtap").__gc
hs.getObjectMetatable("hs.eventtap").__gc = function(...)
print("~~ " .. os.date("%Y-%m-%d %H:%M:%S") .. " : invoking hs.eventtap.__gc")
__originalEventTapGC(...)
end
@cmsj I was keeping it into a local variable in a file that was required in init.lua. I didn't know that that was a problem. I thought that lua's gc only collected nil variables.
@asmagill Thanks for the input. Making the variable global solved the problem
I've been thinking about culling through our issues sometime and making some Wiki articles about common concerns... the question of how garbage collection happens and local versus global is a prime example.
For global variables, you are correct that setting them to nil is necessary for them to be collected; but for local variables, they can be collected as soon as their last reference goes out of scope (going out of scope here means at the end of the function or file where the variable is defined)... this means that unless the local variable is referenced in something that is still "in scope" (being global really just means that it doesn't go out of scope until Hammerspoon is restarted or exited) it can be collected, even if it still holds a value.
Most helpful comment
The current eventtap code detects when Apple disables the eventtap and re-enables it...
The logBreadcrumb method does log this via Crashlog, but not where you can get to it from Hammerspoon, so if you want to verify if this is occurring, you'll need to add
hs.crash.crashLogToNSLog(true)to your init.lua file and then open up the Apple Console application and watch for the message.As @cmsj alludes to, if your eventtap object is not being stored in a global variable or in a local variable that is being referenced by something that is ultimately referenced by a global variable, Lua's own garbage collection could be shutting it down and that won't be logged... You could add something like the following to your init.lua to detect if that is occurring (I use a variant of this when debugging new modules and need to know if/when they get collected):