NSWorkspace running application list is not complete from daemon.

Hi,


We are seeing an issue on 10.14 build which is as followed:


When we try to get list of current running applications on Mac using API:

[NSWorkspace.sharedWorkspace runningApplications], the list of the applications running is always restricted to:

<NSRunningApplication: 0x7fa839200b70 (com.apple.ViewBridgeAuxiliary - 44824)>,

<NSRunningApplication: 0x7fa839200cb0 (com.apple.ViewBridgeAuxiliary - 44964)>,

<NSRunningApplication: 0x7fa839200da0 (com.apple.CoreSimulator.CoreSimulatorService - 44976)>,

<NSRunningApplication: 0x7fa839200e90 (com.apple.WebKit.Storage - 45251)>


instead of including all of the running applications.


The service which is trying to get the list of applications is running as launchd daemon and hits this problem.

However, if we call the same API using the command line tool, it gives the complete list of applications.

This API works fine on builds prior 10.14.


Could you please let us know how can we fix this problem?


Thanks.

Accepted Reply

This is not expected to work. That’s because

NSWorkspace
is part of AppKit and AppKit is not daemon safe. If you call it from a daemon context, there’s no guarantee how it will behave.

I strongly recommend that you read Technote 2083 Daemons and Agents. While it’s quite old, it’s still largely accurate and it explicitly describes the background to the issue you’re seeing.

You wrote:

This API works fine on builds prior 10.14.

No it did not. It seemed to work but you just hadn’t noticed the edge cases. For example, it might have returned the running apps from one GUI login session, but macOS supports multiple GUI login sessions (via both Fast User Switching and remote access) and it was undefined which one you’d get.

How you proceed here depends on your goals. What do you need a list of running applications for?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

This is not expected to work. That’s because

NSWorkspace
is part of AppKit and AppKit is not daemon safe. If you call it from a daemon context, there’s no guarantee how it will behave.

I strongly recommend that you read Technote 2083 Daemons and Agents. While it’s quite old, it’s still largely accurate and it explicitly describes the background to the issue you’re seeing.

You wrote:

This API works fine on builds prior 10.14.

No it did not. It seemed to work but you just hadn’t noticed the edge cases. For example, it might have returned the running apps from one GUI login session, but macOS supports multiple GUI login sessions (via both Fast User Switching and remote access) and it was undefined which one you’d get.

How you proceed here depends on your goals. What do you need a list of running applications for?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hey Quinn,

Thanks for your quick reply. The daemon which we have basically uses this list for app management with Munki Software Distribution.

So what do you suggest? Should we use "NSTask" and call command line "ps" tool to get the list of running applications? Any other API which we could use from daemons?


Regards,

Sanjay.

The daemon which we have basically uses this list for app management with Munki Software Distribution.

I’m going to need more details than that. After you get your lists of running applications, what do you intend to do with that information?

Should we use "NSTask" and call command line "ps" tool to get the list of running applications?

NSTask
is safe to use from a daemon, but I generally don’t recommend using the
ps
command-line tool as an API. There are various better options in this space, but the best option depends on exactly what you’re doing, hence the question above.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Quinn,


We want to see if the application is running and if it does then we are going to show the NSNotification from the user agent to the user. Then user can actually choose to close the application (either he/she can close it or we can terminate it using NSApplication APIs like "terminate" and "forceTerminate").


We also have the user-agent which communicates to daemon, so we are planning to shift this entire logic to user agent so that NSWorkSpace is not needed in daemon anymore. Do you think this would be better or there is any alternative to do it from daemon?


Thanks and regards,

Sanjay

We also have the user-agent which communicates to daemon, so we are planning to shift this entire logic to user agent so that

NSWorkSpace
is not needed in daemon anymore.

I strongly recommend this approach.

The only gotcha here is that you can have multiple GUI login sessions running simultaneously, which means multiple user agents connected to your daemon. Make sure you test that scenario.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Ok thanks Quinn. We would test this usecase as well.