Setting Thread QoS for Mac OS

Hi folks,

Has anyone come up with a way to set the various Thread QoS settings when you run your Xojo app? I have an issue causing an app crash when the background thread (in a shelled process) has been ignored for too long and Mac OS setting its Zombie flag so that I can’t wake it up again.

From one of the crash reports:

Effective Thread QoS Default, Requested Thread QoS Default, Override Thread QoS Unspecified

I’m clutching at straws here …

Is it possible to change the design of the application so that a thread doesn’t get zombied to begin with.

I.e. When work needs to be done, the tread is started, it does its job and then finishes, rather than hanging around? Even consider instigating a new thread instance when work needs to be done and then removing the thread from scope when work is completed?

Not possible - the back end task (BRU) is managing the communication with a tape drive that can take minutes to weeks. With the capacity points of LTO-7 and LTO-8, users often start a job on Friday, let it run, and then come in Monday for the tape change because the first tape filled. BRU must be patient and wait for the user to respond to the tape change request. If they only delay until the next morning, things are mostly good, but if they wait 2 or 3 days the BRU process zombies and we lose communication with it on the UI. There’s no way to stop or suspend the thread as that then prevents BRU from recognizing the tape change and continuing.

We already kill App-Nap and set the sysctl flag for debug.lowpri_throttle_enabled to 0 (off). These QoS messages were new and there’s nothing that I can locate on developer.apple.com that helps.

Of course, there’s this - Minimize Timer Usage and this Energy Efficiency Guide for Mac Apps, but since we don’t have a way to set the Task info for a shell, I don’t see a way to do what we need to do.

What you are doing doesn’t sound very OO. Why are you using a thread and not a timer? Of course, we don’t know anything about your architecture.

Did you goggle your error message? Some folks at Adobe and Citrix also had this problem. Without anything helpful in the answers that I could see, though.

Hi Trixie,

Yes, I’ve tried both timer-based Shell access and Thread/dynamic Shell (as now) and the thread is far more responsive. We used Timer/Shell back in the RB/RS days when a 1GHz G4 was a fast Mac and disk throughout was measured in low 100’s of MB/sec. With newer machines, the loss of performance using a Timer and Shell combination was dropping far too many blocks of data from the back end on the newer, Intel-based Macs.

Yes - I searched and saw the same lack of answers from Apple - right on par with the CoreGraphics and CoreFoundation crashes we’re all also seeing under 10.13. I’ve submitted 13 crash reports to RADAR and have had zero responses - as expected.

To understand the architecture, we are executing a CLI tool that can run for days or even weeks in a couple of instances involving and PB pr more of data. This tool deals with the media requirements and waits for user input when a new tape is required. There’s nothing that I can change about that back-end task’s operation since I also need to handle the incoming data stream to provide info for the user. Using Thread.Suspend when the task prompts for the user’s input and then resuming when the user responds results in an even quicker trip to zombie-ville.

Could you prompt the user and have the thread do something useless in a loop until they respond to the prompt?

That’s what I do - In the thread I loop and check a flag that is set by a timer that checks for the status of the tape drive to see when the user has changed the tape. During the loop I use a me.sleep(1000, False).

However, thinking about this, maybe I could try simply polling the shell in that same loop to see if that’s enough to keep the task active. I’ll report back.

Polling the shell might work.

By “do something useless” I was referring to doing something like incrementing a variable on each loop so that the thread is actively changing something in memory.

That wouldn’t help because it’s not the thread that’s an issue, but the shell.

Ahh, I misunderstood which thread was being killed.

If you have access to the Monkeybread plugins, then you might want to check out https://www.monkeybreadsoftware.net/class-nstaskmbs.shtml

The only question is whether or not the process will be interactive if it’s invoked as an NSTask.

Christian’s NSTask can be interactive through the named pipes, but I also need it to work on Windows and Linux. The test with the added Poll calls is running and we’re keeping an eye on it.