hammerspoon: Memory leak in hs.osascript
I noticed recently that Hammerspoon’s memory footprint on my computer seemed to be growing over time. After doing some investigating using lua-mtrace I tracked down the issue to a line in one of my spoons that calls hs.osascript.javascript.
Here’s a minimal line of code to run in the Hammerspoon console to reproduce the behavior:
test = hs.timer.doEvery(0.5, function() hs.osascript.javascript("") end)
If you open Activity Monitor and go to the Memory tab, you’ll see that Hammerspoon’s memory footprint grows as this timer is running. Running test:stop() to stop the timer stops the memory footprint from increasing.
When the timer is running the lua-mtrace log fills up with lines like this,
@ ....app/Contents/Resources/extensions/hs/osascript/init.lua:101 + 0x600002ad59f0 0x50 s
which corresponds to this line,
local ok, object, descriptor = module._osascript(source, "JavaScript")
which calls the runosascript() function in the internal.m file for the module.
Profiling with Xcode using Instruments confirms this. Here’s the “Heaviest Stack Trace” for runosascript() after running the timer for a minute or so, in case that’s helpful:
56 libdyld.dylib 86.81 MB start
55 Hammerspoon 86.81 MB main /Users/malo/Documents/Code/Hammerspoon/hammerspoon/Hammerspoon/MJAppDelegate.m:364
54 AppKit 86.81 MB NSApplicationMain
53 AppKit 85.24 MB -[NSApplication run]
52 AppKit 83.46 MB -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]
51 AppKit 83.36 MB _DPSNextEvent
50 HIToolbox 65.46 MB _BlockUntilNextEventMatchingListInModeWithFilter
49 HIToolbox 65.46 MB ReceiveNextEventCommon
48 HIToolbox 65.46 MB RunCurrentEventLoopInMode
47 CoreFoundation 65.38 MB CFRunLoopRunSpecific
46 CoreFoundation 65.04 MB __CFRunLoopRun
45 CoreFoundation 29.00 MB __CFRunLoopDoTimers
44 CoreFoundation 29.00 MB __CFRunLoopDoTimer
43 CoreFoundation 29.00 MB __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
42 Foundation 28.86 MB __NSFireTimer
41 internal.so 28.86 MB -[HSTimer callback:] /Users/malo/Documents/Code/Hammerspoon/hammerspoon/extensions/timer/internal.m:51
40 LuaSkin 28.86 MB -[LuaSkin protectedCallAndTraceback:nresults:] /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/LuaSkin/Skin.m:244
39 LuaSkin 28.86 MB lua_pcallk /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/lua-5.3.5/src/lapi.c:969
38 LuaSkin 28.86 MB luaD_pcall /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/lua-5.3.5/src/ldo.c:746
37 LuaSkin 28.86 MB luaD_rawrunprotected /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/lua-5.3.5/src/ldo.c:156
36 LuaSkin 28.86 MB luai_objcttry /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/LuaSkin/lobjectivec_exceptions.m:84
35 LuaSkin 28.86 MB f_call /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/lua-5.3.5/src/lapi.c:943
34 LuaSkin 28.86 MB luaD_callnoyield /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/lua-5.3.5/src/ldo.c:526
33 LuaSkin 28.86 MB luaD_call /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/lua-5.3.5/src/ldo.c:516
32 LuaSkin 28.86 MB luaV_execute /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/lua-5.3.5/src/lvm.c:1134
31 LuaSkin 28.86 MB luaD_precall /Users/malo/Documents/Code/Hammerspoon/hammerspoon/LuaSkin/lua-5.3.5/src/ldo.c:451
30 internal.so 28.86 MB runosascript /Users/malo/Documents/Code/Hammerspoon/hammerspoon/extensions/osascript/internal.m:26
29 OSAKit 28.79 MB -[OSAScript compileAndReturnError:]
28 OpenScripting 28.33 MB OSACompile
27 JavaScript 28.07 MB JavaScriptComponent
26 CoreFoundation 28.07 MB -[NSInvocation invoke]
25 CoreFoundation 28.07 MB __invoking___
24 JavaScriptOSA 28.07 MB -[JSStorage(JSProcedures) compileScriptData:modeFlags:scriptID:]
23 JavaScriptOSA 28.07 MB -[JSStorage addScript:]
22 JavaScriptOSA 28.00 MB -[JSStorageScriptContext initWithScript:]
21 JavaScriptAppleEvents 28.00 MB JSAEContextSetup
20 JavaScriptAppleEvents 26.96 MB JSAEExports
19 JavaScriptAppleEvents 14.77 MB JSAEApplicationConstructor
18 JavaScriptAppleEvents 14.02 MB JSAEApplicationPrototypeCreate
17 JavaScriptAppleEvents 8.09 MB JSAELibraryConstructor
16 JavaScriptAppleEvents 7.60 MB JSAELibraryPrototypeCreate
15 JavaScriptAppleEvents 6.31 MB JSAEObjectSpecifierConstructor
14 JavaScriptAppleEvents 6.07 MB -[JSValue(DefineProperties) defineProperties:]
13 JavaScriptCore 6.07 MB -[JSValue invokeMethod:withArguments:]
12 JavaScriptCore 6.07 MB objectToValue(JSContext*, objc_object*)
11 JavaScriptCore 6.07 MB ObjcContainerConvertor::convert(objc_object*)
10 JavaScriptCore 6.07 MB objectToValueWithoutCopy(JSContext*, objc_object*)
9 JavaScriptCore 6.07 MB -[JSContext(Internal) wrapperForObjCObject:]
8 JavaScriptCore 6.07 MB -[JSWrapperMap jsWrapperForObject:inContext:]
7 JavaScriptCore 6.07 MB -[JSObjCClassInfo wrapperForObject:inContext:]
6 JavaScriptCore 3.24 MB -[JSContext(Internal) wrapperForJSObject:]
5 JavaScriptCore 3.24 MB -[JSWrapperMap objcWrapperForJSValueRef:inContext:]
4 Foundation 3.24 MB -[NSConcreteMapTable setObject:forKey:]
3 Foundation 3.21 MB -[NSConcreteMapTable grow]
2 Foundation 1.61 MB allocateCollectableUnscannedStorage
1 libsystem_malloc.dylib 1.61 MB malloc
0 libsystem_malloc.dylib 1.61 MB malloc_zone_malloc
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 2
- Comments: 19 (18 by maintainers)
We do run hs.osascript scripts on the main thread (easy way to tell - it’s called by Lua->C and we only ever run Lua on the main thread. Secondary way to tell, there’s a
[LuaSkin shared]in the function - that willabort()if it’s not called on the main thread).I think the reality here is that these scripting frameworks are not super well cared for these days, and they are crashy and leaky. On that basis, our only options here are to just accept it as it is, or create some kind of helper binary that we spawn for each OSAScript execution, so its leak/crash problems don’t infect our binary, but we currently don’t have any of the build-time or run-time mechanisms needed for helper binaries.
I’ve been running into this as I pretty heavily use apple script for spotify, chrome, etc. I notice the issue when my whole machine starts slowing down. Reloading hammerspoon seems to temporary resolve it, so until this is fully resolved, this restart binding might be helpful to others:
@malob - Thanks so much for introducing me to
lua-mtrace- I think that’s going to be VERY helpful!In regards to the leak, @cmsj or @asmagill, because of this line of code:
…does this mean we need a
[osa release]somewhere in there?