BTT in race condition: cannot kill it.

I have a touch bar button that executes some applescript that seems to have gone into a race condition (at the moment, I don't know why, but that's irrelevant to this bug).

I'm trying to kill the BTT process from Activity Monitor, but it keeps restarting. I've tried killing BBTRelaunch, but that restarts. I've taken BTT out of my startup items and rebooted the computer, but it still comes back again.

I'm on a 15" MacBook Pro 2017
Mojave (10.14)
Not sure of the BTT version but latest alpha as of a few days ago.

Two questions:

  1. How do I kill it whilst I try to find the solution
  2. Where can find the files that contain the scripts for the touchbar buttons, so that I can edit out the offending code and get back to something that runs?

We can look into what caused the race condition later...

This terminal command will kill it:

killall BetterTouchTool && killall BTTRelaunch

BTT data files can not really be edited by hand as they are binary SQLite database files). They are located in ~/Library/Application Support/BetterTouchTool

Maybe you can restore one of the previous version data files in that folder.

Thanks. That's killed it. How do I restore a data file? There are loads in there - what do I delete and what do I rename to what?

The data for the current version always consists of three files that have the version number in the name.

For example:
btt_data_store.version_2_654_build_0964-wal
btt_data_store.version_2_654_build_0964-shm
btt_data_store.version_2_654_build_0964

You can just rename the files from any previous version to the three current ones (while deleting/renaming the current one)

OK, that's got me back to a state from a while back.

Lost a fair bit of work on my Lightroom touchbar, though. Is there any way to recover data from the other files? Or can I start BTT in a "safe mode" so that it doesn't actually run anything, but I can edit and save out stuff to JSON files.

I found a SQLite DB browser, but they seem to be encrypted...

A safe mode is a good idea - unfortunately I currently don't have something like that.

Yeah it's possible that macOS uses some default encryption on the database files.

You could try removing your license file (xxx.bttlicense) from the ~/Library/Application Support/BetterTouchTool folder. I THINK it won't run the scripts if no license is available and the trial has expired, but you should still be able to edit in that case.

OK, I'll give it a go.

Alternatively you can send the files to me (andreas@folivora.ai) I'll be able to export the data as JSON for you.

Let me try the licence trick first. If that doesn't work, I'll send you the files.

Fixed it.

After I put the old data files in place and got it back to a useable state, I turned OFF TouchBar support in the general settings. That meant I could put the original data files back, without it running the code on startup. That gave me the chance to edit out the offending code, and now it's back to where it was earlier today, before I added the racing code (which, I think, is associated with using get_string_variable).

I have this code (which works fine):

set upcomingEvents to do shell script "/usr/local/bin/icalbuddy -n -nc -nrd -ps "| - |" -iep "title,datetime" -po "datetime,title" -df "%a" -ic "Todoist" -eed eventsToday+7"

if (length of upcomingEvents) > 0 then
set maxSize to 49
set trailing to ""
set nextevent to first paragraph of upcomingEvents
set l to length of nextevent
if l > maxSize + 2 then
l = maxSize + 2
trailing = "…"
end if
set nextevent to (text 3 thru l of nextevent) & trailing
else
set nextevent to "No tasks"
end if

return nextevent

I moved the "do shell script" statement into a named trigger:

set upcomingEvents to do shell script "/usr/local/bin/icalbuddy -n -nc -nrd -ps "| - |" -iep "title,datetime" -po "datetime,title" -df "%a" -ic "Todoist" -eed eventsToday+7"

tell application "BetterTouchTool" to set_string_variable "BTT_TODOIST_TASKS" to upcomingEvents

and replaced that line with:

tell application "BetterTouchTool"
trigger_named "get-todoist-tasks"
try
set upcomingEvents to get_string_variable "BTT_TODOIST_TASKS"
on error
set upcomingEvents to ""
end try
end tell

BTT stops responding with this code in place. The named trigger seems to run fine, so I think the problem is in the trigger_named or the get_string_variable (I think it's this one, because I'm sure I've had problems with it in the past).

Anyway, time to save everything out to JSON files before I bugger up anything else...

Maybe try putting the stuff in separate tell statements.

BTT already does various workarounds to be able to run Apple Script on itself from an Apple Script that it executes itself :smiley: , but maybe there is some limitation I haven't caught yet... (unfortunately Apple Script is not really designed to do that because it always blocks the main thread thereby blocking all other Apple Scripts and deadlocking, BTT uses two helper services to workaround that...)

I changed it to:

--tell application "BetterTouchTool" to (trigger_named "get-todoist-tasks")

set upcomingEvents to ""
tell application "BetterTouchTool"
try
	set upcomingEvents to get_string_variable "BTT_TODOIST_TASKS"
end try
end tell

(Note the trigger_named is commented out).

I manually ran the code in the named trigger to set the variable and that ran fine.

I ran the above and it was also fine - it produced the expected output.

I then uncommented the trigger_named statement, ran it and it stopped responding.

Looking over some of the other code I have, I think I was mistaken in remembering get_string_value as the problem. There are quite a few bits where my natural instinct would be to put the code into a trigger, but I haven't, so I suspect that calling trigger_named from AppleScript (rather than as an action in the widget) is causing the problem.

is the named trigger itself again running an apple script?

Yeah. It's this:

set upcomingEvents to do shell script "/usr/local/bin/icalbuddy -n -nc -nrd -ps \"| - |\" 
           -iep \"title,datetime\" -po \"datetime,title\" -df \"%a\" 
           -ic \"Todoist\" -eed eventsToday+7"

tell application "BetterTouchTool" to 
        (set_string_variable "BTT_TODOIST_TASKS" to upcomingEvents)

(I've added line breaks for convenience - there are only two lines in the script)

Ok, that's probably the problem.

BTT may not be able to apply the Apple Script workarounds in that case. Maybe putting that directly into the Apple Script (without using a named trigger) would fix it.

Yeah, in this case it works without the trigger, since I can rely on the widget setting the variable and it's unlikely to be out of date when other widgets read it.

Probably also explains why a bit of code works in Script Editor but fails when you copy it into BTT...

Yup, when triggered externally it doesn't block the execution in BTT.

I'll check if I can add some more logic to prevent this, but it's very complicated unfortunately (mostly due to a bug in Apple Script that hasn't been fixed in years).

It would be useful to be able to do that, but I can think of a few other things I'd rather have first, though...

(e.g create a preset, then assign an existing set of triggers—maybe a whole section/app—to it. Just because I keep either forgetting to create a new preset before creating a new app touchbar or I create a load of triggers and realise I've got the wrong preset as default.)

I'll add that to the wishlist forum...

It's relatively fast to move triggers between presets:

1.) Activate both presets
2.) Mark the preset which you want to move the triggers to as master preset
3.) Then just cmd+c and cmd+v the triggers (they will be copied from either preset, but pasting will always insert into the current master preset)

That's what I've been doing. Would be nice to be able to select them all at once and do it in one go.