/******************************************************************************** * Copyright (c) 2025-2026 ZF Friedrichshafen AG * * This program and the accompanying materials are made available under the * terms of the Apache License Version 2.0 which is available at * https://www.apache.org/licenses/LICENSE-2.0 * * SPDX-License-Identifier: Apache-2.0 * * Contributors: * Erik Verhoeven - initial API and implementation ********************************************************************************/ #ifndef PROCESS_CONTROL_IFC_H #define PROCESS_CONTROL_IFC_H /** * @brief Process control application parameters. * @details The operating mode is the first parameter of the application. */ enum class EOperatingmode : uint32_t { normal_shutdown_1000ms, ///< Proper shutdown after 1000ms; exit code = 0 emergency_exit_1000ms, ///< Emergency exit after 1000ms; exit code = -20 wait_for_process, ///< Wait for process end; then shutdown; exit code = 0 on proper shutdown, -10 on emergency exit, -20 on timeout terminate_process, ///< Terminate the first process; then shutdown; exit code = 0 }; /** * @brief Process monitor helper class */ class CProcessMonitorHelper : public sdv::IInterfaceAccess, public sdv::process::IProcessLifetimeCallback { public: // Interface map BEGIN_SDV_INTERFACE_MAP() SDV_INTERFACE_ENTRY(sdv::process::IProcessLifetimeCallback) END_SDV_INTERFACE_MAP() /** * @brief Called when the process was terminated. Overload of sdv::process::IProcessLifetimeCallback::ProcessTerminated. * @remarks The process return value is not always valid. The validity depends on the support of the underlying system. * @param[in] tProcessID The process ID of the process being terminated. * @param[in] iRetValue Process return value or 0 when not supported. */ virtual void ProcessTerminated(/*in*/ sdv::process::TProcessID tProcessID, /*in*/ int64_t iRetValue) override { std::unique_lock lock(m_mtxTerminate); m_tProcessID = tProcessID; m_iRetValue = iRetValue; m_bCalled = true; lock.unlock(); m_cvTerminate.notify_all(); } /** * @brief Wait for 5000ms for the process to terminate. * @return Returns 'true' on successful terminate; 'false' due to a timeout. */ bool Wait5000ms() { std::unique_lock lock(m_mtxTerminate); std::chrono::high_resolution_clock::time_point tpStart = std::chrono::high_resolution_clock::now(); while (!m_bCalled && std::chrono::duration(std::chrono::high_resolution_clock::now() - tpStart).count() < 5.0) { m_cvTerminate.wait_for(lock, std::chrono::milliseconds(30)); } std::cout << GetTimestamp() << "Process PID#" << std::dec << m_tProcessID << " has " << (m_bCalled ? "" : "not ") << "terminated." << std::endl; return m_bCalled; } /** * @brief Get the process ID (to be called after successful termination). * @return The process ID provided by the callback event. */ sdv::process::TProcessID GetProcessID() const { std::unique_lock lock(m_mtxTerminate); return m_tProcessID; } /** * @brief Get the return value (to be called after successful termination). * @return The return value provided by the callback event. */ int64_t GetRetValue() const { std::unique_lock lock(m_mtxTerminate); return m_iRetValue; } private: mutable std::mutex m_mtxTerminate; ///< Mutex for process termination conditional variable. std::condition_variable m_cvTerminate; ///< Process termination conditional variable. sdv::process::TProcessID m_tProcessID = 0; ///< Process ID of terminated process. int64_t m_iRetValue = -100; ///< Process return value. bool m_bCalled = false; ///< Set when called (to prevent waiting for condition var). }; #endif // !defined PROCESS_CONTROL_IFC_H