Post not yet marked as solved
I have a Safari Web Extension that communicates with its native App through UserDefaults within an App Group.
The WebExtensionHandler is also used to carry out other functions for the Web Extension on request.
I am currently troubleshooting a bug where a request from the Extension to the WebExtensionHandler remains unanswered.
The bug only occurs on physical devices, in the simulator, it always behaves as expected. When XCode is attached to the App or App Extension process, the bug also does not trigger. When the Console App is used to monitor events on the device, the bug also does not trigger.
Here is the code for the WebExtensionHandler:
import SafariServices
func respondWith(_ context: NSExtensionContext, string: String) {
let response = NSExtensionItem()
response.userInfo = [ SFExtensionMessageKey: string ]
context.completeRequest(returningItems: [response], completionHandler: nil)
}
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
var sharedPrefs = UserDefaults.init(suiteName: "group.eu.waiyu.app")!
func beginRequest(with context: NSExtensionContext) {
let item = context.inputItems[0] as! NSExtensionItem
let message = item.userInfo?[SFExtensionMessageKey] as! Dictionary<String,Any>
switch message["type"] as! String {
// other cases...
case "get_config":
if let config = sharedPrefs.string(forKey: "config") {
respondWith(context, string: config)
} else {
let defaultConfig = message["defaultConfig"]!
respondWith(context, string: defaultConfig as! String)
}
default:
respondWith(context, string: "Unknown Message type")
}
}
}
Even though it appears that something goes wrong when accessing sharedPrefs when the bug is triggered, other requests are answered correctly (before and after triggering the bug).
As per some solutions to similar issues (https://stackoverflow.com/questions/38275395/failed-to-read-values-in-cfprefsplistsource-ios-10) I have tried different App Group IDs:
the main Bundle ID, prefixed with "group."
an ID different from both main bundle and extension bundle, prefixed with "group."
"group.TEAMID." prefix (TEAMID being the developer team id)
Is there anything I can try with regards to the code? Are there any other debugging workflows I can try that do not involve attaching to the device, that might allow me to capture more information about the bug?
Post not yet marked as solved
I have LaunchDaemon plist launching a x86_64 daemon, which worked so far on my M1 Mac mini running Big Sur, but right after the reboot from upgrading to macOS Monterey, I see error launching with EBADARCH error, but when I load the same plist by hand it worked.
2021-10-27 10:23:15.602649 (system/com.[redacted] [530]) : Could not find and/or execute program specified by service: 86: Bad CPU type in executable:
2021-10-27 10:23:15.602661 (system/com.[redacted] [530]) : Service could not initialize: posix_spawn([redacted]) EBADARCH error: 0x6f: Invalid or missing Program/ProgramArguments
2021-10-27 10:23:15.602666 (system/com.[redacted] [530]) : initialization failure: 21A559: xpcproxy + 23196 [815][D33C7462-5256-38E5-AFD4-A1FF694581F3]: 0x6f
2021-10-27 10:23:15.602668 (system/com.[redacted] [530]) : Service setup event to handle failure and will not launch until it fires.
2021-10-27 10:23:15.602671 (system/com.[redacted] [530]) : Missing executable detected. Job: 'com.[redacted]' Executable: '[redacted]'
Post not yet marked as solved
Background
Alright, so there's a lot of voodoo and undocumented stuff going on here but hopefully somebody can help me out. I've reverse engineered how stuff might work based on:
https://opensource.apple.com/source/launchd/launchd-442.21/support/launchctl.c.auto.html
https://developer.apple.com/library/archive/technotes/tn2083/_index.html#//apple_ref/doc/uid/DTS10003794-CH1-SUBSECTION10
I've got a launchdaemon running that spawns another process in the /dev/console bootstrap context in order to act as a remote desktop server. What I'm trying to accomplish here, is to run one of my processes as root in the current gui bootstrap context which is attached to the console.
There are several guesswork states in MacOS (11.6, M1) that I've discovered. When you boot a machine, the loginwindow process is run in the bootstrap context of 88 (_windowserver). This makes sense because this process is created by WindowServer. The current console UID is discoverable by running:
echo "show State:/Users/ConsoleUser" | scutil
You can also introspect loginwindow using launchctl procinfo and friends.
Note that, this is before any login has ever happened on the machine.
In this state I can do anything in the gui bootstrap context by running this from the launchdaemon:
launchctl asuser 88 myprogram
In my case, I'm taking a screenshot using AppKit/CoreGraphics and checking some permissions.
Once a user logs in, that loginwindow gets blessed by the OS and ownership is transferred to the logged in user. If you lock the machine, you're still in the same bootstrap context and everything works as expected. You can also log out and log into another user and everything works as I expect it to in terms of who controls loginwindow.
However, as soon as you hit the "Switch user" button from the lock screen the following happens:
A new loginwindow is spawned with the bootstrap context of root (UID of 0)
launchctl asuser 0 myprog seems not to properly execute within the bootstrap context of root.
My guess is that: 1 is a bug(?), the fast user switching bootstrap context should probably run as 88 rather than 0.
A "fix" is running pkill loginwindow which nukes all gui sessions and restarts one loginwindow running in the bootstrap context of 88. This is of course not an acceptable solution.
Doing the same thing using launchctl bootstrap gui/0 doesn't work either. I understand that the concept of "bootstrap gui/0" and "asuser 0" sounds nonsensical and it probably is. I'm just trying to find a working solution here.
Is there a more proper way of being able run as root in the bootstrap context of a logged in/not yet logged in loginwindow?
In case anyone is curious, I'm porting this to MacOS: https://fleetdeck.io
I'm writing a Agent Application that records the Screen and I'm trying to keep the recording going even when the user logs out. I've been reading about LaunchAgents and LaunchDaemons. From what I understand a Prelogin LaunchAgent is my best bet since I need NSApplication to keep my process going and to access the screens. I'm only able to relaunch the app after login or to reopen the app when the os closes it. But the recording process is interrupted. Here is what I have as far as my LaunchAgent.
My prelogin LaunchAgent (to open the app during the LoginWindow context)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.myApp.prelogin</string>
<key>LimitLoadToSessionType</key>
<string>LoginWindow</string>
<key>RunAtLoad</key>
</true>
<key>ProgramArguments</key>
<array>
<string>/Library/myApp/myAgent0</string>
<string>service</key>
<array>
<key>QueueDirectories</key>
<array>
<string>/etc/myApp/service</string>
</array>
</dict>
</plist>
Per user launch agent (to keep the application open while a file exists in the path of QueDirectories)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.myApp.peruser</string>
<key>LimitLoadToSessionType</key>
<string>Aqua</string>
<key>RunAtLoad</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/Library/myApp/vmyAgent0</string>
<string>service</string>
</array>
<key>QueueDirectories</key>
<array>
<string>/etc/myApp/service</string>
</array>
</dict>
</plist>
And then a daemon that I was suggested to add.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.myApp.server</string>
<key>ProgramArguments</key>
<array>
<string>/Library/myApp/myAgent0</string>
<string>-service</string>
</array>
<key>QueueDirectories</key>
<array>
<string>/etc/myApp/service</string>
</array>
</dict>
</plist>
Currently the application get closed down when the user logs out and gets reopened when the user logs back in or every time I close it (until I remove the file from QueueDirectories). I'm not sure if it gets open during LoginWindow but I don't see any recordings of that so I don't think it does. I know it is possible since VNC viewer does it (you can remotely log into your Mac).
I'm not even sure I'm on the right track and I found this other question which tells me I'm on the wrong side using NSApplication for something like this? I'm in need of confirmations lol.
Thank you in advance.
Post not yet marked as solved
Hello,
We created a sample app delegate to test whether applicationDidFinishLaunching runs as expected or not (code as follows). The observed behavior was that the executable
prints both applicationWillFinishLaunching and applicationDidFinishLaunching in the case when we're using an RDP connection to the mac
prints only applicationWillFinishLaunching in case of ssh connection to the mac
Why is this behavior different and how can I ensure it runs correctly with ssh? Kindly help.
#include <unistd.h>
#include <sys/types.h>
#include <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <SystemConfiguration/SCDynamicStore.h>
@interface TWAppKitAppDelegate : NSObject <NSApplicationDelegate>
@end
@implementation TWAppKitAppDelegate
// Launching Applications
- (void)
applicationWillFinishLaunching: (NSNotification *) pNotification
{
NSLog(@"applicationWillFinishLaunching");
}
- (void)
applicationDidFinishLaunching: (NSNotification *) pNotification
{
NSLog(@"applicationDidFinishLaunching");
}
// Managing Active Status
- (void)
applicationWillBecomeActive: (NSNotification *) pNotification
{
}
- (void)
applicationDidBecomeActive: (NSNotification *) pNotification
{
}
- (void)
applicationWillResignActive: (NSNotification *) pNotification
{
}
- (void)
applicationDidResignActive: (NSNotification *) pNotification
{
}
// Terminating Applications
#if 0
- (NSApplicationTerminateReply)
applicationShouldTerminate:(NSNotification *) pNotification
{
return NSApplicationTerminateReply::NSTerminateNow;
}
#endif
- (BOOL)
applicationShouldTerminateAfterLastWindowClosed:(NSNotification *) pNotification
{
return NO;
}
- (void)
applicationWillTerminate:(NSNotification *) pNotification
{
}
- (BOOL)
application:(NSApplication *) pSender
openFile: (NSString *) pFileName
{
return YES;
}
- (void)
application:(NSApplication *) pSender
openFiles: (NSArray<NSString *> *) pFileNames
{
}
@end
int
main (int pArgc, char ** pArgv)
{
NSApplication * app;
TWAppKitAppDelegate * appdelegate;
app = [NSApplication sharedApplication];
appdelegate = [[TWAppKitAppDelegate alloc] init];
[app setDelegate:appdelegate];
[NSApp run]; //NOTE: Apple never 'returns' from here
NSLog(@"Function main called \n");
return 0;
}
Post not yet marked as solved
I’m trying to implement a simple cross-process notify/observe system, using a pthread mutex and condition variable in shared (mapped) memory. It seems to be working fine (on macOS 11.6) if one process calls pthread_cond_wait and then another calls pthread_cond_broadcast — the waiting process indeed wakes up.
However, if two processes try to observe at the same time, the second one's call to pthread_cond_wait fails with EINVAL. I’m wondering if I’m just doing something wrong in my setup, or if this sort of usage isn’t supported.
Basically I create and mmap a file, initialize a pthread mutex and condition in the mapped memory using the setpshared attributes, then lock the mutex and notify or wait on the condition. Actual source code here:
Here’s the code that does the pthreads stuff
Here’s the outer code that opens and mmaps the file
I’m aware that there are a few dozen 🙄 Apple IPC APIs that are probably preferred over these POSIX ones. I’ve used some in the past. I’m doing it this way because:
(a) this is in a cross-platform project and it would be nice to share code between Unix platforms, at least Darwin and Linux;
(b) the thing I’m notifying/observing about is a database file, so tying the notifications to a side file next to the database provides ideal scoping;
(c) it’s similar in principle to the usage of shared memory for locking in SQLite and LMDB. (The difference is, I’m doing notification not locking.)
Any advice?
—Jens
Post not yet marked as solved
Running a child process using Process (or NSTask in Objective-C) is easy, but piping data to and from the child’s stdin and stdout is surprisingly tricky. I regularly see folks confused by this. Moreover, it’s easy to come up with a solution that works most of the time, but suffers from weird problems that only show up in the field [1].
I recently had a couple of DTS incidents from folks struggling with this, so I sat down and worked through the details. Pasted below is the results of that effort, namely, a single function that will start a child process, pass it some data on stdin, read the data from the child’s stdout, and call a completion handler when everything is done.
There are some things to note here, some obvious, some not so much:
I’ve included Swift and Objective-C versions of the code. Both versions work the same way. The Swift version has all the comments. If you decide to base your code on the Objective-C version, copy the comments from there.
I didn’t bother collecting stderr. That’s not necessary in many cases and, if you need it, it’s not hard to extend the code to handle that case.
I use Dispatch I/O rather than FileHandle to manage the I/O channels. Dispatch I/O is well suited to this task. In contrast, FileHandle has numerous problems working with pipes. For the details, see Whither FileHandle?.
This single function is way longer than I’d normally tolerate. This is partly due to the extensive comments and party due to my desire to maintain focus. When wrapping Process it’s very easy to run afoul of architecture astronaut-ism. Indeed, I have a much more full-featured Process wrapper sitting on my hard disk, but that’s going to stay there in favour of this approach (-:
Handling a child process correctly involves some gnarly race conditions. The code has extensive comments explaining how I deal with those.
If you have any questions or comments about this, put them in a new thread. Make sure to tag that thread with Foundation and Inter-process communication so that I see it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] Indeed, this post shows that I’ve made this sort of mistake myself )-:
Post not yet marked as solved
I've got an mach-o executable that runs from launchDaemon plist file, and is communicating with other processes using unix domain socket. The file that backs this socket created in /tmp. However, this cause the executable to fail reading the file unless given full disk access.
I'd like to find a location for the socket file, which is shared to all processes and doesn't require full disk access. the executable reside in /Library/Application Support/myProj/bin/exec_file
is there such location ? Perhaps can i use the same location of the executable itself ?
Post not yet marked as solved
I'm opening a different thread to a question that was asked about a year ago.
I'm trying to get the output of "which" so that I can automatically find programs for the user. I've used the code that was provided in that thread which is:
func launch(tool: URL, arguments: [String], completionHandler: @escaping (Int32, Data) -> Void) throws {
let group = DispatchGroup()
let pipe = Pipe()
var standardOutData = Data()
group.enter()
let proc = Process()
proc.executableURL = tool
proc.arguments = arguments
proc.standardOutput = pipe.fileHandleForWriting
proc.terminationHandler = { _ in
proc.terminationHandler = nil
group.leave()
}
group.enter()
DispatchQueue.global().async {
// Doing long-running synchronous I/O on a global concurrent queue block
// is less than ideal, but I’ve convinced myself that it’s acceptable
// given the target ‘market’ for this code.
let data = pipe.fileHandleForReading.readDataToEndOfFile()
pipe.fileHandleForReading.closeFile()
DispatchQueue.main.async {
standardOutData = data
group.leave()
}
}
group.notify(queue: .main) {
completionHandler(proc.terminationStatus, standardOutData)
}
try proc.run()
// We have to close our reference to the write side of the pipe so that the
// termination of the child process triggers EOF on the read side.
pipe.fileHandleForWriting.closeFile()
}
it works fine for all of the normal command line routines but not for custom ones such as avr-gcc or any other that is installed via homebrew. I can use "which avr-gcc" in terminal and it shows the path just fine but in my app it returns nothing where as if I search for the path of something like ls in my app it returns it just fine.
What could be the cause of this?
Post not yet marked as solved
I have an application that upon installation, registers a custom URL protocol (scheme) like foo:// using the lsregister command line tool.
Recently I noticed that the custom URL protocol is missing after an upgrade of macOS (Catalina to Big Sur). It appears that the upgrade de-registers the custom URL protocol while my application is still installed as it was before the macOS upgrade.Yet, any application functionality depending on its custom URL protocol is broken.
The only workaround seems to reinstall my application, or at minimum re-register the custom URL protocol manually.
Is this expected behavior for macOS upgrades? Do applications need to re-register any custom URL protocol again after a macOS upgrade? Why are these not retained as one would expect?
I try to exclude some activities from UIActivity.
It works as expected when exclusion is done directly with the activity, as with:
UIActivity.ActivityType.message,
UIActivity.ActivityType.airDrop
but not when activity is declared with an init as with:
UIActivity.ActivityType(rawValue: "net.whatsapp.WhatsApp.ShareExtension"),
UIActivity.ActivityType(rawValue: "com.ifttt.ifttt.share"),
So, with the following code:
let excludedActivityTypes = [
UIActivity.ActivityType.message,
UIActivity.ActivityType.airDrop,
UIActivity.ActivityType(rawValue: "net.whatsapp.WhatsApp.ShareExtension"),
UIActivity.ActivityType(rawValue: "com.ifttt.ifttt.share")
]
let activityVC = UIActivityViewController(activityItems: [modifiedPdfURL], applicationActivities: nil)
activityVC.excludedActivityTypes = excludedActivityTypes
message and airDrop do not show, but WhatsApp and IFTTT still show.
I have tested with
activityVC.completionWithItemsHandler = { (activity, success, modifiedItems, error) in
print("activity: \(activity), success: \(success), items: \(modifiedItems), error: \(error)")
}
that WhatsApp and IFTTT services are effectively the ones listed here.
When selecting WhatsApp, print above gives:
activity: Optional(__C.UIActivityType(_rawValue: net.whatsapp.WhatsApp.ShareExtension)), success: false, items: nil, error: nil
Post not yet marked as solved
Hi All,
I have coded a TCP Server packaged inside C++ static library. I am using this static library within the iOS Swift UI application. I have coded a simple UI which has a button, on click of which I want to start the TCP server (which is written in C++ and inside the linked static library). After the TCP server is started, I want to push the application to background and then run the client application which is going to interact with this TCP server from the backgrounded SwiftUI application. I want the TCP server to be running even the application goes to the background mode as I have another user interface application which is going to interact with the TCP server on the same device. I tried using background task, but I don't know whether I am doing something wrong there, or I cannot achieve what I want using the BackgroundTask functionality available in iOS.
The main thing here is, the TCP server code is in C++ inside static library and I want to start the TCP server from SwiftUI application layer. I have managed to call C++ function from Swift that part is available.
Can anyone show me the right path here ? How do I keep the BSD Socket based TCP Server active while the application is in Background mode ?
Hi there!
Please advice how I can subscribe to listening system events (Lock Screen/User log off/Device mounted/etc)?
I try to use NSDistributedNotificationCenter to do it, but I can receive only own notifications =(
This is the my test Console application:
//
// main.m
// EventsListener
//
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#include <iostream>
@interface MyClass : NSObject
-(void)subscribe;
-(void)handleNotification:(NSNotification*)notification;
@end
@implementation MyClass : NSObject
-(void)subscribe
{
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:nil object:nil];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(handleNotification2:) name:nil object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification3:) name:nil object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification4:) name:@"com.apple.screenIsLocked" object:nil];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(handleNotification4:) name:@"com.apple.screenIsLocked" object:nil];
}
-(void)handleNotification:(NSNotification*)notification
{
NSLog(@"handleNotification: %@", notification);
}
-(void)handleNotification2:(NSNotification*)notification
{
NSLog(@"handleNotification2: %@", notification);
}
-(void)handleNotification3:(NSNotification*)notification
{
NSLog(@"handleNotification3: %@", notification);
}
-(void)handleNotification4:(NSNotification*)notification
{
NSLog(@"handleNotification3: %@", notification);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
MyClass* mc = [MyClass new];
[mc subscribe];
[[NSNotificationCenter defaultCenter] postNotificationName:@"test notification" object:nil];
NSLog(@"Press enter to abort");
getchar();
}
return 0;
}
What wrong I does?
Thanks!
Post not yet marked as solved
My IDE like app built with electron allows to spawn a terminal by means of forkpty. Although this is also working in the MAS build, the sandboxed environment results in the terminal being mostly unusable (which I expected).
From a technical perspective, what would be the best way to allow an unrestricted terminal experience? Obviously I'd need the terminal process to be spawned outside the sandboxed environment.
My initial thinking was that I could create some kind of "Helper" app that the user has to run manually. This app would then run outside the sandbox and would provide a terminal API to my sandboxed app by means of TCP or IPC Socket communication. But this would have multple drawbacks:
Uncomfortable for the user because he has to spawn the helper app
The communication sockets could be abused by others
I'm sure there exist many other apps on the Mac App Store that face the same problem (running a process outside the sandboxed environment).
What is the best way to solve this? Is it even allowed?
Post not yet marked as solved
Can we access and perform actions over the UIElements of other apps from my app in iOS?
For example: Suppose i want to access the button of Whatsapp, and Uber from my app.
Post not yet marked as solved
Hello -
TLDR - Is there any sample code to demonstrate how one goes about creating dedicated XPCServices to wrap ARM and Intel-specific dylibs?
We have an app we're looking at moving to a universal binary.
In that same app we have a framework that currently wraps R functionality by directly linking to /Library/Frameworks/R.framework/Current .
R now has dedicated Intel and ARM builds (https://mac.r-project.org/)
After watching the 2020 WWDC session "Port your Mac app to Apple silicon" (https://developer.apple.com/videos/play/wwdc2020/10214/?time=2006), it sounds like, for us to deploy a universal binary I should look at wrapping the R interaction bits into dedicated ARM and Intel XPC services so the appropriate architecture for R will run.
Is anyone aware of any sample code or extended documentation demonstrating the ins and outs of how to think about this?
Thank you
Hi, how could I get the command line arguments of a process given its audit token.
My app is a Content Filter Network Extension written in swift. I can obtain the audit token from NEFilterFlow but I can't figure out how to get the process arguments, I was able to get the pid from the audit token using audit_token_to_pid.
Post not yet marked as solved
Hi,
I have a macOS application say Main.app which uses Helper App say Helper.app with UI support. Helper.app is placed inside Main.app/Contents/Library/LoginItems/Helper.app.
Helper.app is launched using NSWorkSpace and when user opts to launch Helper.app on login, SMLoginItemSetEnabled is turned ON for Helper.app.
Main.app and Helper.app communicate with each other via NSConnection.
Helper app supports set of features based on some Condition and same condition is used to validate a feature in Main.app. Hence, Main.app talks to Helper.app to check if a feature can be validated.
1) Can someone write their version of Helper.app with same bundle identifier as my Helper.app and expose a connection with same name (when my Main.app and Helper.app is not running).
2) Now when Main.app is launched, it get connected to 3rd party Helper.app.
There are two versions of Main.app Main.app and Helper.app both are sandboxed and Belong to same group.
Main.app and Helper.app both are not sandboxed (But, hardened run time is enabled). Groups are not defined.
Thank you.
Regards,
Deepa
We define an event handler for OpenURL
NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
[appleEventManager setEventHandler:self
andSelector:@selector(handleGetURLEvent:withReplyEvent:)
forEventClass:kInternetEventClass andEventID:kAEGetURL];
And we handle it here:
(void)handleGetURLEvent:(NSAppleEventDescriptor *)event
withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
// Handler type stuff
}
If I'm debugging in Xcode, I see a SIGCONT before the handler is called. When I continue from the SIGCONT, I enter the handler and everything is fine.
This causes automated tests to break, and is generally a pain in the you-know-where. Outside of Xcode it's fine.
How can I make it stop doing this? Is there some Xcode setting I've overlooked?
Hello,
I am facing an issue with NSTask (Process), NSPipe (Pipe) and NSFileHandle (FileHandle).
I have an app that executes a child process (command line utility) and gets its output via Pipe instances set as standardI/O of Process instance.
I can observe two logic flows: Once the child process exits, -[Process readabilityHandler] gets called where I gather the $0.availableData.
Once the child process generates output (i.e. print() is executed by the child process), -[Process readabilityHandler] also gets called which makes sense. This is the case when exit() is not called by the child process (i.e. continuous execution).
However, when LLDB is detached, #2 is false, i.e. -[Process readabilityHandler] is not called.
Wrong behaviour also happens if I don't rely on readabilityHandler, but instead use Notification to receive changes in data availability. In such case, notification gets called continuously with empty data (even though child process does generate the output).
If I don't create Pipe instance for standardI/O of the Process, then readabilityHandler does get called, but with an empty data continuously.
I have created a DTS #756462540, since this doesn't make any sense.
Prerequisites*
app is not sandboxed
Big Sur 11.0.1 (20B29)
Xcode 12.3 (12C33)