diff --git a/mediapipe/framework/calculator_graph.cc b/mediapipe/framework/calculator_graph.cc index d803d714..b49930b7 100644 --- a/mediapipe/framework/calculator_graph.cc +++ b/mediapipe/framework/calculator_graph.cc @@ -631,7 +631,13 @@ absl::Status CalculatorGraph::PrepareServices() { for (const auto& [key, request] : node->Contract().ServiceRequests()) { auto packet = service_manager_.GetServicePacket(request.Service()); if (!packet.IsEmpty()) continue; - auto packet_or = request.Service().CreateDefaultObject(); + absl::StatusOr packet_or; + if (allow_service_default_initialization_) { + packet_or = request.Service().CreateDefaultObject(); + } else { + packet_or = absl::FailedPreconditionError( + "Service default initialization is disallowed."); + } if (packet_or.ok()) { MP_RETURN_IF_ERROR(service_manager_.SetServicePacket( request.Service(), std::move(packet_or).value())); diff --git a/mediapipe/framework/calculator_graph.h b/mediapipe/framework/calculator_graph.h index 93dbfe8d..354694e3 100644 --- a/mediapipe/framework/calculator_graph.h +++ b/mediapipe/framework/calculator_graph.h @@ -405,6 +405,34 @@ class CalculatorGraph { return service_manager_.GetServiceObject(service); } + // Disallows/disables default initialization of MediaPipe graph services. + // + // IMPORTANT: MediaPipe graph serices, essentially a graph-level singletons, + // are designed in the way, so they may provide default initialization. For + // example, this allows to run OpenGL processing wihtin the graph without + // provinging a praticular OpenGL context as it can be provided by + // default-initializable `kGpuService`. (One caveat here, you may still need + // to initialize it manually to share graph context with external context.) + // + // Even if calculators require some service optionally + // (`calculator_contract->UseService(kSomeService).Optional()`), it will be + // still initialized if it allows default initialization. + // + // So far, in rare cases, this may be unwanted and strict control of what + // services are allowed in the graph can be achieved by calling this method, + // following `SetServiceObject` call for services which are allowed in the + // graph. + // + // Recommendation: do not use unless you have to (for example, default + // initialization has side effects) + // + // NOTE: must be called before `StartRun`/`Run`, where services are checked + // and can be default-initialized. + absl::Status DisallowServiceDefaultInitialization() { + allow_service_default_initialization_ = false; + return absl::OkStatus(); + } + // Sets a service object, essentially a graph-level singleton, which can be // accessed by calculators and subgraphs without requiring an explicit // connection. @@ -644,6 +672,9 @@ class CalculatorGraph { // Object to manage graph services. GraphServiceManager service_manager_; + // Indicates whether service default initialization is allowed. + bool allow_service_default_initialization_ = true; + // Vector of errors encountered while running graph. Always use RecordError() // to add an error to this vector. std::vector errors_ ABSL_GUARDED_BY(error_mutex_);