What happens to my app when my Mac goes to sleep? - macos

When Mac OS X goes to sleep, due to closing a laptop or selecting "Sleep" from the Apple menu, how does it suspend an executing process?
I suppose non-windowed processes are simply suspended at an arbitrary point of execution. Is that also true for Cocoa apps, or does the OS wait until control returns to the run loop dispatcher, and goes to sleep in a "known" location? Does any modern OS do that, or is it usually safe enough to simply suspend an app no matter what it is doing?
I'm curious, because allowing sleep to occur at any moment means, from the app's perspective, the system clock could suddenly leap forward by a significant amount. That's a possibility I don't usually consider while coding.

Your app is interrupted exactly where it is that moment if the CPU is actually currently executing code of your app. Your app constantly gets execution time by the task scheduler, that decides which app gets CPU time, on which core, and for how long. Once the system really goes to sleep, the scheduler simply gives no time to your app any longer, thus it will stop execution wherever it is at that moment, which can happen pretty much everywhere. However, the kernel must be in a clean state. That means if you just made a call into the kernel (many libC functions do) and this call is not at some safe-point (e.g. sleeping, waiting for a condition to become true, etc.) or possibly holding critical kernel locks (e.g. funnels), the kernel may suspend sleep till this call returns back to user space or execution reaches such a safe-point before it finally cancels your app from the task scheduler.
You can open a kernel port and register for sleep/wake-up events. In that case, your app will receive an event, when the system wants to go to sleep. You have several possibilities. One is to reply to it, that the system may progress. Another one is to suspend sleep; however, Apple says certain events can be suspended at most 30 seconds, after that, the system will just continue, whether your app likes it or not. And finally, you can cancel it; though not all events can be canceled. If the system already decided it will go to sleep, you can only suspend this by at most 30 seconds or allow it at once, you cannot cancel it. However, you can also listen to an event, where the system asks apps, if it is okay to go to sleep now and there you can reply "no", causing a sleep to be canceled.
The difference between "Is it okay to sleep" and "I'm planing on going to sleep" is: The first one is sent if the power saving settings are applied, that is, if the user has not moved the mouse or typed anything for the time configured there. In that case the system will just ask, if sleep is okay. An app like Apple's DVD Player will say "no", because most likely the user watches a DVD and thus doesn't interact with the computer, still no reason to go to sleep. OTOH, if the user closes his Mac Book, apps are not asked, the system will go to sleep for sure and just informs apps, that have now up to 30 seconds to react to it.
Wake-up events can also be quite interesting to catch. E.g. if your system wakes up, open files might be inaccessible (an external drive has been unplugged) or network sockets won't work any longer (network has changed). So you may re-init certain app parts before using them and running into errors that are more or less expected.
Apple's page regarding catching these events.

It depends on your app.
If you are interacting with external systems (think networking or doing something over usb/firewire,etc) then it might be affected. An application running on OSX gets to run for a limited time ( max 10ms ) , after which it is interrupted by the kernel which schedules a new process from the process queue to run on the CPU. This is transparent for the application , which "thinks" that it runs all the time on the CPU. Thus , a transition to sleep is no different - apart from the time jumping ahead.
If you need to be aware that there was a transition to sleep mode please refer to this tech note which details how to receive notifications about the state change : Registering and unregistering for sleep and wake notifications

I believe it will just suspend all apps wherever they happen to be.
Remember, this happens all the time anyway. Applications are constantly suspended and resumed due to context switching. So, really, the clock could jump between any 2 instructions in your app, though usually not in a noticable/significant way.
If the OS waited for the app to return to some main loop you could run into situations where applications cause the sleep to hang. If they're doing a lot of work and not returning to the run loop dispatcher they would prevent the machine from going to sleep. That wouldn't be very good. :)

And if you set the time it also appears to leap forward to the running programs. Nothing special either.

Check out this Wikipedia article. Cavver is correct in stating that things like network connections may time out, and thus those services may be interrupted.

Related

Is it safe to perform actions after receiving Kernel-Power events?

I want to perform an action before every hibernation, but the only event I see in Event Viewer which gets called after I hibernate the device is Kernel-Power (187). Is it safe to perform actions after receiving this event or is it too late at that point and I shouldn't risk it?
Mainly, what I want to do is shutdown WSL before hibernating the device, because it becomes very laggy on wake up otherwise. Also, sometimes after waking up from hibernation, wsl --shutdown gets stuck so I need to reboot.
Didn't try because it feels a bit risky, that's why I came to ask.

SC_MONITORPOWER starts background tasks

Summary
When putting the monitor in sleep mode in Windows 10, Windows seems to execute some tasks that don't get executed with the screen on.
This is interfering with our software, and we need to get rid of it.
Ful story
For a hardware device with a touch screen, I need to be able to turn off the touch screen when it's not in use, for durability reasons. Windows has a message that you can send to turn it off, SC_MONITORPOWER. More specifically:
SendMessage(hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
This works fine, but when the screen is off, Windows is apparently sometimes performing some tasks that it doesn't do when the screen is on. We are careful to never write anything to the screen in this situation (that causes huge problems when the screen is off, in fact just having a blinking cursor in a DOS box is using up half a core when the screen is off).
Our software requires a callback to be executed every 0.25 ms. We have turned nearly every task, service and several other things in Windows off, and with the screen on, I can run our software for days without ever missing a callback. But with the screen off I get hiccups. The callback already runs at the highest possible priority.
So there is apparently something that we missed when we turned all services and tasks off. There appear to be 2 causes of hiccups:
One happens once every 10-30 hours or so (not sure of the exact time, it seems to vary). But it always happens 5 times, with EXACTLY 5 minutes (at most a few milliseconds off) in between (so in total it happens 5 times in a 25 minute period).
Beside this, we get a single hiccup typically every 4-10 hours, but the time between occurrences doesn't seem to be very constant so there could also be multiple causes.
I'm a bit at a loss here, and running analysis software can easily interfere with our own software, making it harder to detect when these hiccups really occur and when they are caused by running the analysis software.
Interestingly, I have seen this 5-times-every-5-minutes thing also on a completely different system (different hardware, different OS version), when recording audio in Adobe Audition. Audition misses pieces of audio every 5 minutes in this case, and I think it also only happens when the monitor is in sleep mode and you're not logged in remotely.
We have already tried to turn the touch screen off using direct monitor commands like Nircmd does, and it doesn't support those. My guess is that the SC_MONITORPOWER message is triggering more things in Windows, and if we can turn them off, that would fix our problem. Any ideas?
System
Intel i5-8700 with 6 cores, Windows LTSB, no extra software installed except our own.
Never mind, problem solved. It was not an extra task that was being started, it was one of the existing Windows processes that for some reason only causes issues when the display is off. Since killing them is not an option (Windows will just restart them), I've suspended the following processes, and the culprit is one of these (I don't know which one yet):
sihost.exe
igfxEM.exe (I very much suspect this one)
RuntimeBroker.exe
dllhost.exe
taskhostw.exe
explorer.exe
I have to continue testing a bit longer to be absolutely certain, but so far with these tasks all suspended I've not seen a missed callback in the last 38 hours. I don't know yet if there are any drawbacks to suspending all these things, so I'll try to find the cause(s) and suspend only that/those.

Windows 8/10 API Detect suspended process

UWP (or "Metro") apps in Windows 8/10 are frequently suspended when they are not in the foreground. Apps in this state continue to exist but no longer consume CPU time. This change seems to have been introduced to improve performance on low-power/storage devices like tablets and phones.
Please can I ask, what is the most elegant and simple method to detect an app in this state?
I can see 2 possible solutions at the moment:
Call NtQuerySystemInformation() and the enumerate each process and each thread. A process is "suspended" if all threads are in the suspended state. This approach will require a lot of code and critically NtQuerySystemInformation() is only semi-documented and could be removed in a future OS. NtQueryInformationProcess() may also offer a solution with the same problem.
Call GetProcessTimes() and record the counters for each process. Wait some time (minutes) and check these again. If the process counters haven't changed then assume the process is suspended. This is a hack and I may get shot down for even thinking of it.
Jim
The second one (GetProcessTimes() … wait … and check these again. 
If the process counters haven’t changed then assume the process is suspended)
is less reliable. 
If a process is waiting for input (e.g., keyboard, mouse, or network)
and not getting any, it will use very little CPU time
and will appear to be suspended by this approach.

Cocoa program can't be stopped

I'm trying to write an OS X app that uses a serial port. I found an example (cocoa) and got it running in Xcode 4. On the first run, it opens the port and I'm able to exchange data with the hardware.
If I try to change the port the program goes rogue. The pinwheel starts and the UI is unresponsive. I can't stop the program from Xcode, nor can I kill it from Terminal, or Force Quit. Force Quit of Xcode doesn't do it. Although the PID goes away with a kill from Terminal, the UI is still present with the merrily spinning pinwheel.
The only way out is a re-boot. Any ideas on how to track down the errant code are welcome. I'm new to Cocoa/Objective C, so simple terms are better.
Most likely it became a zombie. It should show up in ps auxww (or similar) with a 'Z' in its status. Activity Monitor might also still show it.
This is relatively common when working with hardware, such as a serial port. Zombies can arise for either of two reasons, most likely the first in this case:
The process is blocked in a kernel call of some kind, that's not interruptible.
The process has exited but its parent hasn't acknowledged that (via wait() or similar).
In the first case it's usually a fundamental bug or design flaw of some kind, and you may not have any good options short of figuring out exactly what code path tickles the problem, and avoiding that.
In the second case the solution is generally simple - find the parent process of your zombie and kill it. Repeat as necessary until your zombie gets adopted by a parent process that does call wait() to reap it (launchd will do this if nothing else).

How to Safely Force Shutdown of Mac

What I want
I'm developing a little app to force me to only work at certain times of day - I need something to force me to stop working in the evenings so I can be more effective in the day.
The option within OS X to shut down my machine at a certain time is too easy to cancel. And you can always log back in afterwards.
I want my app to quit all applications whether they have unsaved work or not.
What I've tried
I thought of killing the loginwindow process, but I've read that this can cause data corruption.
I've come across the shutdown command - I'm using sudo shutdown -h +0 to shutdown immediately. This appears to be just the ticket, but I'm worried that it might cause data corruption if, say, Disk Utility is doing some kind of scan.
Is the shutdown command safe?
Can the shutdown command cause corruption? Or is it safe to use? Is there a better way of forcing shutdown safely?
Use AppleScript to tell application "System Events" to shut down.
The shutdown command sends running processes a signal to terminate, giving them a chance to do clean up work, if needed. So generally, when an application receives this signal (SIGTERM(inate)) it should wrap up and exit.
IIRC in Snow Leopard (10.6) Apple added something called fast-shutdown (or similar) which will send processes that have been flagged as being ok with it a SIGKILL signal, shutting them down without chance for cleanup work. This is supposed to make shutdown faster. The default is that applications still get SIGTERM and have to opt-in for SIGKILL; and they can mark themselves as "dirty", i. e. having unsaved work and do not want to be killed forcibly.
So while shutting down in the middle of a disk utility run will abort whatever disk utility is doing, IMHO it would not cause data corruption in general. However depending on the operation you are currently running, you could end up with an incomplete disk image or a half-formatted partition. Maybe you want to refrain from using it when you know the end of your configured work time is coming close.
Using cron to schedule the shutdown is a viable option if you want it to happen at a specified time. If you want it to happen after a certain amount of time after you log in, you could use the number parameter to shutdown to specify say 8 hours from now.
If you want to lose unsaved work then shutdown -h is your only answer.
However, anyone who has debugged a full-screen app on OS X knows that is it very easy (some say too easy) for an app to capture the screen and render the computer essentially useless (without SSHing from another computer to kill the process.) That's another alternative.
the recommended way to schedule a shutdown of your computer on a regular basis is in the system preferences -> Energy Saver panel. Click on the "schedule" button in the lower right hand corner. the rest is self explanatory...
Forcing your computer to shut down (and discard any unsaved work) doesn't sound like a good idea to me. Wouldn't it be easier and safer to just set an alarm clock to remind yourself when you should stop working, and walk away from your computer when it rings? (That's what I do.)
Edit: That might have come across as a bit rude, which was not my intention at all. (I had no intention of making fun of your question or anything like that.) I just think that this would be a better solution to this problem :)
Maybe cron is installed on your computer? It's wonderful =)

Resources