getppid() 在双击 macOS 捆绑应用程序时返回 1

huangapple go评论76阅读模式
英文:

getppid() returns 1 when double-clicking macOS bundle app

问题

I have a macOS GUI app, which is also functionally capable of running as a background service i.e., Agent or a Daemon.

The main entry point is main.swift file, where I set some values and invoke some OS calls to understand if my app was launched a service (Agent or Daemon) or a GUI app.


import Foundation

// Set some variables
// Call an ObjC++ func which does the following:
// {
// if(getppid() == 1) { 
// // Prepare app to function as a daemon/agent
// // Return to swift
// } else {
// // Prepare app to function as a GUI app
// // Return to swift
// }

// Back in swift layer, start initializing the NSApplication object and 
// set the NSApplicationDelegate. 

Lets not get into why I'm not using @main attribute, which removes this boilerplate code... Now, when I build this app using Xcode, launch it from the builds folder, I see that getppid() - the Linux OS call to know the parent process ID, returns 1, which means, app is a daemon or an agent (as all services are children of the init process, which has pid of 1).

I'm not creating any new threads nor invoking fork(), both of which can cause the main thread to be returned to OS... which leads to init process adopting the app.

Why does getppid() return 1 when the app is launched by double clicking from Finder? Finder is the parent process in this case, right?

Update1:

As pointed out in Arthur's answer and Barmar's comment (in the question) - When I launch Safari and then checked its PPID using the 'top' command in terminal.

Output:

PID    COMMAND  %CPU TIME     #TH    #WQ #PORTS MEM   PURG  CMPRS PGRP  PPID 
5134   Safari   0.0  00:02.72  7      4   443    55M  9792K 0B    95134 1
94818  Xcode    0.0  00:17.81  10     3   569    469M 864K  0B    94818 1

As shown above, the PPID of Safari and Xcode is 1.

英文:

I have a macOS GUI app, which is also functionally capable of running as a background service i.e., Agent or a Daemon.

The main entry point is main.swift file, where I set some values and invoke some OS calls to understand if my app was launched a service (Agent or Daemon) or a GUI app.

// main.swift

import Foundation

// Set some variables
// Call an ObjC++ func which does the following:
// {
//   if(getppid() == 1) { 
//    // Prepare app to function as a daemon/agent
//    // Return to swift
//   } else {
//     // Prepare app to function as a GUI app
//     // Return to swift
//   }

// Back in swift layer, start initializing the NSApplication object and 
// set the NSApplicationDelegate. 

Lets not get into why I'm not using @main attribute, which removes this boilerplate code...
Now, when I build this app using Xcode, launch it from the builds folder, I see that getppid() - the Linux OS call to know the parent process ID, returns 1, which means, app is a daemon or an agent (as all services are children of the init process, which has pid of 1).

I'm not creating any new threads nor invoking fork(), both of which can cause the main thread to be returned to OS... which leads to init process adopting the app.

Why does getppid() return 1 when app is launched by double clicking from Finder? Finder is the parent process in this case, right?

Update1:

As pointed out in Arthur's answer and Barmar's comment (in the question) - When I launch Safari and then checked its PPID using the 'top' command in terminal.

Output:

PID    COMMAND  %CPU TIME     #TH    #WQ #PORTS MEM   PURG  CMPRS PGRP  PPID 
5134   Safari   0.0  00:02.72  7      4   443    55M  9792K 0B    95134 1
94818  Xcode    0.0  00:17.81  10     3   569    469M 864K  0B    94818 1

As shown above, the PPID of Safari and Xcode is 1.

答案1

得分: 1

抱歉,我无法提供翻译,因为你的请求是要求不提供翻译。如果你有其他需要,请随时告诉我。

英文:

There is no valid process-tree in macOS world, unfortunately.

All unix stuff like getppid will return something valid only for the processes launched in a unix way, let's say running some console binaries from Terminal could show you behaviour you expect here.

GUI processes are launched on macOS in a complex way including 1+ IPC from the real source process who wants something to launch to the launchd.

Regarding your initial goal, I would say the most straightforward will be just to add some commandline argument or env variable into its launch plist, and check it then: if it is present - the app is launched as agent/daemon, if it is not - use GUI logic.

I've answered a question alike (a bit more complex) before here, if you want to read more on topic

huangapple
  • 本文由 发表于 2023年4月10日 22:10:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75977851.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定