in idb_companion/Server/FBIDBServiceHandler.mm [1039:1091]
Status FBIDBServiceHandler::launch(grpc::ServerContext *context, grpc::ServerReaderWriter<idb::LaunchResponse, idb::LaunchRequest> *stream)
{@autoreleasepool{
idb::LaunchRequest request;
stream->Read(&request);
idb::LaunchRequest_Start start = request.start();
NSError *error = nil;
FBProcessOutput *stdOut = FBProcessOutput.outputForNullDevice;
FBProcessOutput *stdErr = FBProcessOutput.outputForNullDevice;
NSMutableArray<FBFuture *> *completions = NSMutableArray.array;
if (start.wait_for()) {
dispatch_queue_t writeQueue = dispatch_queue_create("com.facebook.idb.launch.write", DISPATCH_QUEUE_SERIAL);
id<FBDataConsumer, FBDataConsumerLifecycle> consumer = pipe_output(idb::ProcessOutput_Interface_STDOUT, writeQueue, stream);
[completions addObject:consumer.finishedConsuming];
stdOut = [FBProcessOutput outputForDataConsumer:consumer];
consumer = pipe_output(idb::ProcessOutput_Interface_STDERR, writeQueue, stream);
[completions addObject:consumer.finishedConsuming];
stdErr = [FBProcessOutput outputForDataConsumer:consumer];
}
FBProcessIO *io = [[FBProcessIO alloc]
initWithStdIn:nil
stdOut:stdOut
stdErr:stdErr];
FBApplicationLaunchConfiguration *configuration = [[FBApplicationLaunchConfiguration alloc]
initWithBundleID:nsstring_from_c_string(start.bundle_id())
bundleName:nil
arguments:extract_string_array(start.app_args())
environment:extract_str_dict(start.env())
waitForDebugger:(start.wait_for_debugger() ? YES : NO)
io:io
launchMode:start.foreground_if_running() ? FBApplicationLaunchModeForegroundIfRunning : FBApplicationLaunchModeFailIfRunning];
id<FBLaunchedApplication> launchedApp = [[_commandExecutor launch_app:configuration] block:&error];
if (!launchedApp) {
if (error.code != 0) {
return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String);
} else {
return Status(grpc::StatusCode::FAILED_PRECONDITION, error.localizedDescription.UTF8String);
}
}
// Respond with the pid of the launched process
idb::LaunchResponse response;
idb::DebuggerInfo *debugger_info = response.mutable_debugger();
debugger_info->set_pid(launchedApp.processIdentifier);
stream->Write(response);
// Return early if not waiting for output
if (!start.wait_for()) {
return Status::OK;
}
// Otherwise wait for the client to hang up.
stream->Read(&request);
[[launchedApp.applicationTerminated cancel] block:nil];
[[FBFuture futureWithFutures:completions] block:nil];
return Status::OK;
}}