@@ -683,20 +683,22 @@ void handle_crash(int sig)
683683}
684684
685685// / This will start a new device by forking and executing a
686- // / new child
687- void spawnDevice (uv_loop_t * loop,
688- DeviceRef ref,
689- std::vector<DeviceSpec> const & specs,
690- DriverInfo& driverInfo,
691- std::vector<DeviceControl>&,
692- std::vector<DeviceExecution>& executions,
693- std::vector<DeviceInfo>& deviceInfos,
694- std::vector<DataProcessingStates>& allStates,
695- ServiceRegistryRef serviceRegistry,
696- boost::program_options::variables_map& varmap,
697- std::vector<DeviceStdioContext>& childFds,
698- unsigned parentCPU,
699- unsigned parentNode)
686+ // / new child.
687+ // / @return the PID of the new process (or 0 if we are in the driver)
688+ std::string spawnDevice (uv_loop_t * loop,
689+ DeviceRef ref,
690+ std::vector<DeviceSpec> const & specs,
691+ DriverInfo& driverInfo,
692+ DriverControl& driverControl,
693+ std::vector<DeviceControl>&,
694+ std::vector<DeviceExecution>& executions,
695+ std::vector<DeviceInfo>& deviceInfos,
696+ std::vector<DataProcessingStates>& allStates,
697+ ServiceRegistryRef serviceRegistry,
698+ boost::program_options::variables_map& varmap,
699+ std::vector<DeviceStdioContext>& childFds,
700+ unsigned parentCPU,
701+ unsigned parentNode)
700702{
701703 // FIXME: this might not work when more than one DPL driver on the same
702704 // machine. Hopefully we do not care.
@@ -761,6 +763,15 @@ void spawnDevice(uv_loop_t* loop,
761763 putenv (strdup (DeviceSpecHelpers::reworkTimeslicePlaceholder (env, spec).data ()));
762764 }
763765 execvp (execution.args [0 ], execution.args .data ());
766+ // In the general case we never end up here, because execvp is used.
767+ // Once we move to plugins however, the run the plugin without loading
768+ // a new environment so the new pid can be used to identify.
769+ //
770+ // Let's stop immediately so that we can attach debuggers from here.
771+ driverControl.forcedTransitions = {
772+ DriverState::DO_CHILD,
773+ DriverState::BIND_GUI_PORT};
774+ return spec.id ;
764775 } else {
765776 O2_SIGNPOST_ID_GENERATE (sid, driver);
766777 O2_SIGNPOST_EVENT_EMIT (driver, sid, " spawnDevice" , " New child at %{pid}d" , id);
@@ -844,6 +855,7 @@ void spawnDevice(uv_loop_t* loop,
844855
845856 // Let's add also metrics information for the given device
846857 gDeviceMetricsInfos .emplace_back (DeviceMetricsInfo{});
858+ return " " ;
847859}
848860
849861void processChildrenOutput (uv_loop_t * loop,
@@ -2108,15 +2120,25 @@ int runStateMachine(DataProcessorSpecs const& workflow,
21082120 runningWorkflow.devices [di], controls[di], deviceExecutions[di], infos, allStates);
21092121 } else {
21102122 DeviceRef ref{di};
2111- spawnDevice (loop,
2112- ref,
2113- runningWorkflow.devices , driverInfo,
2114- controls, deviceExecutions, infos,
2115- allStates,
2116- serviceRegistry, varmap,
2117- childFds, parentCPU, parentNode);
2123+ frameworkId = spawnDevice (loop,
2124+ ref,
2125+ runningWorkflow.devices ,
2126+ driverInfo,
2127+ driverControl,
2128+ controls, deviceExecutions, infos,
2129+ allStates,
2130+ serviceRegistry, varmap,
2131+ childFds, parentCPU, parentNode);
2132+ // We are in the child in this case. Do not continue spawning.
2133+ if (!frameworkId.empty ()) {
2134+ break ;
2135+ }
21182136 }
21192137 }
2138+ // Do not bother about the rest of the scheduling if we are in the child.
2139+ if (!frameworkId.empty ()) {
2140+ break ;
2141+ }
21202142 handleSignals ();
21212143 handleChildrenStdio (&serverContext, forwardedStdin.str (), childFds, pollHandles);
21222144 for (auto & callback : postScheduleCallbacks) {
0 commit comments