Hammerspoon / hammerspoon

Staggeringly powerful macOS desktop automation with Lua
http://www.hammerspoon.org
MIT License
11.84k stars 578 forks source link

hs.osascript.javascript calls cause hammerspoon to die with "Service exited due to signal: Bus error: 10 sent by exc handler[0]" #1474

Closed 2shortplanks closed 6 years ago

2shortplanks commented 7 years ago

Hammerspoon (version 0.9.54) has recently started randomly quitting on me randomly. Looking in console:

Jun 28 09:56:09 travis com.apple.xpc.launchd[1] (org.hammerspoon.Hammerspoon.37184[29697]): Service exited due to signal: Bus error: 10 sent by exc handler[0]

This problem started after I started some code that checks if I'm in a Google Meet meeting or not every 15 seconds or so and changes my Slack Status if need be:

function chrome_meeting()
    ran_ok, output = hs.osascript.javascript([[
        (() => {
          let windows = Application("Google Chrome").windows();
          for (let i = 0; i<windows.length; i++) {
             let window = windows[i];
             let tabs = window.tabs();
             for (let j = 0; j < tabs.length; j++ ) {
                let tab = tabs[j];
                let url = tab.url()
                var m = url.match(new RegExp("^https://meet[.]google[.]com/([a-z]{3}-[a-z]{4}-[a-z]{3})"));
                if (m) {
                    return m[1]
                }
             }
          }
        })()
    ]])
    return output
end

current_meeting_status = nil
function check_chrome_status()
    meeting = chrome_meeting()
    if (not(current_meeting_status == meeting)) then
        current_meeting_status = meeting
        if (meeting) then
            setSlackStatus(slackStatusForMeet(meeting))
        else
            clearSlackStatus()
        end
    end
end

hs.timer.doEvery(15, check_chrome_status)

I don't think it's to do with the setSlackStatus or clearSlackStatus functions because the death is happening when I'm not changing state - my gut tells me it's the JXA that's the problem.

cmsj commented 7 years ago

@2shortplanks is there any obvious pattern here? Like does it crash/notcrash when Chrome is/isn't running, when you are using/notusing Meet, or if Slack is/isn't running?

2shortplanks commented 7 years ago

There's no pattern that I can see. It crashed while I was out at lunch, and Chrome and Slack were both running then without a google meet url being present.

2shortplanks commented 7 years ago

Oh, and it shouldn't relate to if Slack is or isn't running; The setSlackStatus method makes a HTTP call to the slack servers.

function clearSlackStatus()
    setSlackStatus("","")
end

function formEncode(kv)
    string = ""
    for key,value in pairs(kv) do
        string = string ..
            hs.http.encodeForQuery(key) ..
            "=" ..
            hs.http.encodeForQuery(value) ..
            "&"
    end
    string = string:sub(1, -2)
    return string;
end

function setSlackStatus(emoji,text)
    hs.http.asyncPost('https://slack.com/api/users.profile.set', formEncode({
        token=slack_token,
        profile=hs.json.encode({
            status_emoji=emoji,
            status_text=text,
        })
    }), nil, function ()
    end)
end
2shortplanks commented 7 years ago

@cmsj Okay, I narrowed it down to a small test case...this kills hammerspoon on my system usually within about twenty seconds or so:

function code()
    hs.osascript.javascript([[ true ]]);
    print("Still alive");
end

hs.timer.doEvery(0.05, code);
latenitefilms commented 7 years ago

FYI: I can reproduce this crash.

cmsj commented 7 years ago

Can you reproduce it with this?

function code()
    hs.osascript._osascript([[ true ]],"javascript");
    print("Still alive");
end

hs.timer.doEvery(0.05, code);
2shortplanks commented 7 years ago

@cmsj No, but that code is actually executing AppleScript which doesn't seem to have the same problem (note the case of javascript)

If I do this:

function code()
    hs.osascript._osascript([[ true ]],"JavaScript");
    print("Still alive");
end

hs.timer.doEvery(0.05, code);

Then it dies just as before.

cmsj commented 7 years ago

@2shortplanks good catch on the capitalisation :)

Ok, but that's helpful to know that it still crashes in that case - that means it's not our result processing code. That gets us down to Apple's OSAScript framework, and one method call on the result object we get back from OSAScript.

I've just transposed the very basics of _osascript into a standaline command line application and running it in an infinite loop produces a crash within 2 seconds on my Mac. I also took out any processing of the result, and the crash still occurs, which means this is almost certainly an issue with Apple's OSAScript framework.

My guess is that they simply didn't expect people would be evaluating scripts this quickly, and it looks like the underlying framework is accumulating threads/memory until it hits some kind of limit.

I'll file a bug with Apple and then one of four things will happen:

1) Nothing 2) They'll fix it 3) They'll tell me I'm using this wrong and should change my code 4) They'll tell me I'm using this wrong and to stop wanting to run scripts this often

Thanks very much for your help isolating this!

cmsj commented 6 years ago

FWIW https://www.openradar.appspot.com/radar?id=6056096036814848 is the openradar mirror of the Radar I filed. I'm going to close this issue because there's nothing else we can do right now, and the fix would have to come from Apple anyway.