Coming from windows development, I'm trying to understand macOS architecture and how to do certain things. I've already read the Root and Login Sessions AND Service and Daemons AND User Switch Notifications documentation so will frame the questions accordingly.
-
On Windows, there's a concept of User Sessions, each of which contain One or more WindowStations, each of which contain One or more Desktops. Each user gets at least 3 desktops (e.g. Login/Lock/UAC, Screensaver, and default desktop). From what I understand about macOS, it only has Sessions and then a single Desktop. Is that correct? i.e. same display surface is used to display user's desktop, screensaver, sudo prompt and lock screen?
-
What about login screen? Does each user get its own login screen process/window running in their session? or is there a common login screen for all users running in one particular session (root?). How does Fast User switching effect login screen?
-
In a daemon, is it possible to get active console session ID? console meaning the session being displayed on the monitor, whether its login screen, lock screen, user's desktop etc.
-
In a daemon, is it possible to get session switch notifications? E.g. user logged-in and now their desktop is being displayed, user logged-out and now we're back on login screen, or user switched to another user (Fast User switching). How do I get notification of such events in daemon?
-
If no user is logged in which session is pre-login agent running in? and after login does the session ID assigned to pre-login agent stay the same and user's session is assigned a new session ID?
-
Is there always one and only one pre-login agent running?
-
Is it possible to launch pre-login agent and user agents on-demand with custom commandline arguments from a daemon?
I'm trying to understand macOS architecture
If you haven’t already, I recommend that you read through Technote 2083 Daemons and Agents. While it’s old, and could really do with an update, the core concepts it describes are still valid.
From what I understand about macOS, it only has Sessions and then a single Desktop. Is that correct?
Yes. The terminology is very different but:
-
Each is limited to a single GUI login session.
-
That session has an associated window server session [1].
-
That window server session is used for all GUI work related to that login session. This includes, for example, screen saver unlock.
There’s an interesting wrinkle here: GUI authorisation plug-in code runs as a different user, _securityagent
, but has some access to that window server session.
What about login screen? Does each user get its own login screen process/window running in their session?
I don’t see how that question makes sense. The login screen lets you choose the user, so at least some part of it must necessarily run in some user-independent context.
The pre-login session is implemented using a combination of processes running as either root
or _securityagent
.
How does Fast User switching effect login screen?
When you explicitly navigate to the login window itself, it switches to the pre-login session, spinning it up if necessary.
You have to be careful here. The exact relationship between pre-login sessions, GUI login sessions, and window server sessions is considered an implementation detail. Those implementation details are visible if you look hard enough — by installing a pre-login agent, or via Endpoint Security — but you can’t assume that the current behaviour is how it’ll always work. For example, if you fast user switch from user A to user B, there may or may not be a pre-login session spun up in between.
In a daemon, is it possible to get active console session ID?
Yes, but it’s best to avoid doing that. This question is predicated on the assumption that there’s only a single GUI login session visible on screen at a time. That’s not true. With screen sharing it’s possible to have multiple GUI login sessions active simultaneously [2].
FYI, the best way to get the current console user from a daemon is SCDynamicStoreCopyConsoleUser
. This is based on the System Configuration framework dynamic store, which has built-in notification support, so you can be notified of changes as well.
In a daemon, is it possible to get session switch notifications?
Yes and no. You can get notifications from System Configuration framework, as I mentioned above, but that has the same limiting assumption.
There are two good ways to learn about login sessions:
-
If you’re doing security stuff, Endpoint Security has relevant events.
-
Otherwise, your best option is to install a global
launchd
agent. The system will start an instance of this as sessions come and go, and each instance can use check-in with your daemon (typically using XPC) and notify it of any relevant state updates. I talk about this in TN2083.
IMPORTANT This daemon-with-zero-or-more-helper-agents architecture has stood the test of time. It worked correctly on macOS 10.5 and continues to work correctly on macOS 15. I’ve helped many folks who’ve tried to take shortcuts here and then found that their code broke as the system evolved.
If no user is logged in which session is pre-login agent running in?
A pre-login session.
after login does the session ID assigned to pre-login agent stay the same and user's session is assigned a new session ID?
Which session ID? There are various different ways to identify a session on macOS, and the exact behaviour here is changes depending on which one you use.
If you use the daemon-with-zero-or-more-helper-agents architecture, you rarely need to worry about session IDs, because the XPC connection between the agent and your daemon identifies the session.
Is there always one and only one pre-login agent running?
No.
It’s common for no instances of your pre-login agent to be running, for example, once the user has logged in.
I think it’s safe to assume that there’ll be at most one instance of your pre-login agent running. I think. But, honestly, I’d try to avoid writing code in a way that assumes that. If you use the daemon-with-zero-or-more-helper-agents architecture, you shouldn’t need to make that assumption. Rather, each agent should report its session information to your daemon, which can coordinate things from there.
Is it possible to launch pre-login agent and user agents on-demand … from a daemon?
Yes. It’s tricky, but it can be done.
with custom commandline arguments
No.
Asking this question suggests that your thinking is ‘upside down’. Rather than have the daemon monitor the current sessions and an start agent in each session, have the system start your agents as sessions come and go, and then have those agents ‘check in’ with your daemon.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] That’s an internal concept, not something with a public API.
[2] I always wished that we’d support multiple users on physical consoles. After all, you can plug-in multiple monitors, multiple keyboards and mice, and so on. Sadly, I don’t think that’ll ever happen.