Status FBIDBServiceHandler::xctrace_record()

in idb_companion/Server/FBIDBServiceHandler.mm [1642:1711]


Status FBIDBServiceHandler::xctrace_record(ServerContext *context,grpc::ServerReaderWriter<idb::XctraceRecordResponse, idb::XctraceRecordRequest> *stream)
{@autoreleasepool{
  __block idb::XctraceRecordRequest recordRequest;
  __block pthread_mutex_t mutex;
  pthread_mutex_init(&mutex, NULL);
  __block bool finished_writing = NO;
  dispatch_queue_t queue = dispatch_queue_create("com.facebook.idb.xctrace.record", DISPATCH_QUEUE_SERIAL);
  // @lint-ignore FBOBJCDISCOURAGEDFUNCTION
  dispatch_sync(queue, ^{
    idb::XctraceRecordRequest request;
    stream->Read(&request);
    recordRequest = request;
  });

  FBXCTraceRecordConfiguration *configuration = translate_xctrace_record_configuration(recordRequest.start());

  NSError *error = nil;
  id<FBDataConsumer> consumer = [FBBlockDataConsumer asynchronousDataConsumerOnQueue:queue consumer:^(NSData *data) {
    idb::XctraceRecordResponse response;
    response.set_log(data.bytes, data.length);
    pthread_mutex_lock(&mutex);
    if (!finished_writing) {
      stream->Write(response);
    }
    pthread_mutex_unlock(&mutex);
  }];
  id<FBControlCoreLogger> logger = [FBControlCoreLoggerFactory compositeLoggerWithLoggers:@[
    [FBControlCoreLoggerFactory loggerToConsumer:consumer],
    _target.logger,
  ]];

  FBXCTraceRecordOperation *operation = [[_target startXctraceRecord:configuration logger:logger] block:&error];
  if (!operation) {
    pthread_mutex_lock(&mutex);
    finished_writing = YES;
    pthread_mutex_unlock(&mutex);
    return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String);
  }
  // @lint-ignore FBOBJCDISCOURAGEDFUNCTION
  dispatch_sync(queue, ^{
    idb::XctraceRecordResponse response;
    response.set_state(idb::XctraceRecordResponse::State::XctraceRecordResponse_State_RUNNING);
    stream->Write(response);
    idb::XctraceRecordRequest request;
    stream->Read(&request);
    recordRequest = request;
  });
  NSTimeInterval stopTimeout = recordRequest.stop().timeout() ?: DefaultXCTraceRecordStopTimeout;
  if (![[operation stopWithTimeout:stopTimeout] succeeds:&error]) {
    pthread_mutex_lock(&mutex);
    finished_writing = YES;
    pthread_mutex_unlock(&mutex);
    return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String);
  }
  NSArray<NSString *> *postProcessArgs = extract_string_array(recordRequest.stop().args());
  // @lint-ignore FBOBJCDISCOURAGEDFUNCTION
  dispatch_sync(queue, ^{
    idb::XctraceRecordResponse response;
    response.set_state(idb::XctraceRecordResponse::State::XctraceRecordResponse_State_PROCESSING);
    stream->Write(response);
  });
  NSURL *processed = [[FBInstrumentsOperation postProcess:postProcessArgs traceDir:operation.traceDir queue:queue logger:logger] block:&error];
  pthread_mutex_lock(&mutex);
  finished_writing = YES;
  pthread_mutex_unlock(&mutex);
  if (!processed) {
    return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String);
  }
  return drain_writer([FBArchiveOperations createGzippedTarForPath:processed.path queue:queue logger:_target.logger], stream);
}}