Mac OS X Mojave - application suspended upon screen lock?

I have an application that will, more often than not, have to run unattended overnight. It generates checksums and creates a digital package format of arbitrary data sets, per the Library of Congress Bagit specification. Yesterday I ran the first large scale test, on 908 files, roughly 1.5TB of data - most of these are quicktime files or WAV files, so the checksums take quite some time.

This morning I came in and saw that it was almost exactly where I would have expected it to be when my screen went to sleep about an hour after I left. To be clear, the computer is not asleep, just the screen. Hard drives are set so they never spin down.

Moments after I arrived and saw that it had barely budged from last night, it started running again, suggesting that the application was suspended all night.

How can I prevent this? Other applications, such as DropBox, remain working all the time. I regularly set up DropBox uploads that go for 5-6 hours before going home at night. Same with Chrome - We often have to upload files to Amazon Prime Video that take 10+ hours, so we do that overnight, and it’s never been an issue.

Xojo 2017r3, MacOS X Mojave, 64bit application

Check out NSProcessInfoMBS and the method beginActivity from the MBS plugin.

You may also want to run your app as a local or global daemon, so it can run when the user logs out.

Does this mean the entire application has to be refactored into a console app? I mean, I’m kind of heading in that direction anyway, in order to take advantage of multiple core machines, but right now it’s all GUI. When I google this, everything points to console apps.

Maybe NSAppSleepDisabled still works?
Just search this Forum for ideas…:

(edit) just found this:

So it’s going to be NSProcessInfo for a Desktop.app. If not MBS, then @Sam Rowlands might have something…: https://forum.xojo.com/conversation/post/78698

Thanks. i’ll look into this. As this application will also be compiled for Windows, are there similar issues there that I should be prepared for?

Probably so. You really should have built the functionality in to a service, and have it controlled by, and showing status within, a GUI app. That’s the best way to do what you want if it should execute without user intervention.

So I’ve got NSProcessInfoMBS running and it’s still suspending when the user is logged out (which happens on screen sleep on my machine, or when I log in from home via TeamViewer then disconnect – this triggers a logout, which in turns stops the application from running until I log back in).

I’ve tried calling NSProcessInfoMBS from application start, and also from each of the individual threads that do the processing work, but it doesn’t seem to stick.

Is there something else that might be causing this to happen?

Thanks!

Do your processing with a console based application, last time I checked these are not napped by default. Probably has changed.

Other than that my honest advice at this point; I would recommend that you use one of your DTS incidents at Apple and request assistance.

Quite frankly I am a surprised that the screen going to sleep is considered a user logout, and therefore anything that the user was doing MUST be stopped. However it doesn’t actually surprise me anymore with this current Apple and I had begin to suspect something like this was happening when I walk away leaving my machine Notarizing builds (the upload to Apple appears to get interrupted, but Apple’s functions don’t acknowledge this, instead they just sit there doing nothing).

I may end up doing that, but it’s a major rewrite to do it that way and I don’t really have time right now so I’m hoping there’s a workaround.

Further clarification: the issue is more about the lock screen than screen sleep. Is that the same as a logout? I honestly have no idea. I was conflating the lock and sleep two because I didn’t realize there was a setting in the system prefs on Mojave to throw up the lock screen after a certain period of time after screen sleep. So last night, remotely, I set that to 8 hours before it locks, to see what happens. I logged in again a couple hours later and the processing in my app had barely progressed.

I think this is because when a teamviewer session ends, the lock screen on the remote machine (the one in my office running my app) comes up. Every single time I end a teamviewer session. From a security perspective this makes sense. And I don’t want to have my computer set to 8 hours before locking, so that’s not a good workaround either for when I’m in the office.

Super frustrating. Ultimately the console app is going to be the best solution anyway, because I’d prefer to run it on linux in the console anyway, but we just have too much other stuff going on right now to make that kind of change.

Thanks

I don’t know for sure, but I do know what causes App Nap is all the windows to the app been occluded / not currently visible. So while this is frustrating and not helpful, it kinda makes sense that if nothing is being sent to the screen, then the windows are not visible to the user and therefore the app goes into low power mode.

Pretty much sums up how I feel about almost everything at the moment.

I tend to agree with Sam that you are being “app napped”, and in GUI applications the fix for that for me has always been NSProcessInfoMBS. Here is what I do:

  • Create App level property called ActivityToken, type NSProcessInfoActivityMBS
  • Where I want to disable app nap I do this:
// Disable OSX app nap
#if TargetMacOS then
  dim ProcessInfo as NSProcessInfoMBS = NSProcessInfoMBS.processInfo
  app.ActivityToken = ProcessInfo.beginActivity(NSProcessInfoMBS.NSActivityUserInitiated, "Keep timer running")
#endif
  • Where I want to re-enable app nap I do this:
// Enable OSX app nap
#if TargetMacOS then
  app.ActivityToken = nil
#endif

You can do that around sections of code where long processes are running, or do in the main window open and close events, or whatever is appropriate in your app.

EDIT: Perhaps the reason yours did not “stick” is the activity token went out of scope? That is why I put in App properties

Thanks. In my case, I made a simple method that turns AppNap on or off, depending on the parameter you pass it. I call this before each long process, as well as on App.Open. Does that not have the same effect? Unless I’m mistaken, my call to my AppNap method wouldn’t go out of scope until the thread calling it is killed, which doesn’t happen until the process it’s doing is complete.

So does this mean that Activity Monitor is not telling the truth about AppNap? Because it’s saying it’s off for my app as well as all the MD5 instances I’m calling via a shell

In my experience, ActivityMonitor has always correctly reported the status. Or at least it told me Yes until I implemented the above, then told me No.

I was just guessing you were perhaps going out of scope. If this didn’t help, sorry for the noise…

eh - no problem. The more ideas the better!

Any progress on this? I’ve gone back into it as I would like to prevent App Wrapper from being napped while it’s submitting to Apple. I’ve realized that I may mis specified some of the options, so I’ve updated the code.

https://www.ohanaware.com/xojo/AppNapNSProcessInfo.zip

I changed the settings on that mac so the system doesn’t log me out when I do an overnight run. It’s not ideal, but that seems to work. And I’m finding that I get much better performance on the old Xeon mac pros we have, which we don’t use logins on at all since they’re shared machines. It’s mostly just annoying on my iMac because that’s my dev machine and I can’t leave it for long stretches without ensuring it won’t log me off.

I can’t make it work correctly with TeamViewer though, since that seems to force a logout at the end of the teamviewer session, probably for security reasons. It doesn’t seem to have anything to do with app nap though, at least as far as I can tell from my testing.

I don’t know if AnyDesk will work any different in that regard, but I switched to it from TeamViewer because of the licensing costs. I can say I’m not logged out when I stop remote access, but then I am pretty sure I was not when using TeamViewer either. I do have it configured to allow unattended access instead of requiring user permission on each connect.