LinuxStarter.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarXCore::core
19 * @author Nicola Miskowiec
20 * @date 2016
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25
26#pragma once
27
28#include <optional>
29#include <string>
30#include <vector>
31
34#include "ApplicationStarter.h"
35
37{
38 /**
39 * @class LinuxStarter
40 * @ingroup exec
41 * @brief Starts applications in Linux. Shouldn't be used in any other OS, due to system calls being used.
42 * Applications started this way will still run, even when the main application dies.
43 * Can also be used to request the status of an application.
44 */
46 {
47 public:
49
50 /**
51 * Starts an application. Forks, creates a daemon and starts the executable.
52 * @param application application to be started
53 */
55 StatusManager statusManager,
56 const std::string& commandLineParameters = "",
57 bool printOnly = false) override;
58
59 /**
60 * Returns the status of an application.
61 * @param application application whose status is returned
62 * @return status of the application
63 */
64 virtual std::string getStatus(Data_Structure::ApplicationInstancePtr application,
65 StatusManager statusManager) override;
66
67 private:
68 /**
69 * What a probe of a single pid could establish.
70 *
71 * The distinction between Dead and Indeterminate matters: only a *confirmed* death may
72 * make us forget the pid of an application. Treating "could not read /proc" as a death -
73 * which is what the status probe used to do - permanently loses a running application,
74 * because nothing ever looked for it again.
75 */
76 enum class ProcessState
77 {
78 /// The process exists and is scheduled or sleeping.
79 Alive,
80 /// The process provably no longer exists.
81 Dead,
82 /// The process exists but its state could not be established, or it could not be read
83 /// at all while still being present in /proc.
84 Indeterminate
85 };
86
87 /**
88 * Sets SIGCHLD to SIG_IGN for the whole process, so that the applications we launch and
89 * never wait for do not pile up as zombies.
90 *
91 * Called before every launch rather than once, because the disposition can be taken over
92 * by anything else in the process - Qt's QProcess does so on first use - which switches
93 * the kernel's auto-reaping off again without our noticing.
94 */
95 static void EnsureChildrenAreReaped();
96
97 /**
98 * @brief probeProcessState reads the scheduler state of the process with the given pid.
99 *
100 * Takes the pid instead of the application so that it cannot observe a pid that is
101 * concurrently changed by a starter or stopper thread halfway through.
102 */
103 static ProcessState probeProcessState(int pid);
104
105 /**
106 * @brief findRunningProcess looks for a live process belonging to `application` among all
107 * processes whose executable name matches, and returns its pid, or -1 if there is none.
108 *
109 * This is what lets the ScenarioManager recover an application whose pid it lost, and what
110 * lets it see an application that was started outside of it. Candidates are attributed via
111 * the `--Ice.Config=` argument the ScenarioManager passes on launch; a candidate that
112 * carries a config belonging to a *different* application instance is rejected outright,
113 * and an ambiguous set of candidates is never guessed at.
114 *
115 * @param ambiguous set to true when processes matched but could not be attributed to
116 * exactly one application - the caller should report Unknown rather than Stopped.
117 */
118 static int findRunningProcess(const Data_Structure::ApplicationInstancePtr& application,
119 bool& ambiguous);
120
121 /**
122 * @brief adoptRunningProcess looks for a live process belonging to `application` via
123 * findRunningProcess() and, if it finds one, takes ownership of its pid.
124 *
125 * Called on every path that would otherwise report "Stopped", so that neither a lost pid
126 * nor a launch outside the ScenarioManager leaves a running application shown as stopped.
127 *
128 * @return the status to report for the application.
129 */
130 static std::string
131 adoptRunningProcess(const Data_Structure::ApplicationInstancePtr& application,
132 StatusManager& statusManager);
133
134 /**
135 * @brief rediscover looks for a live process belonging to `application` and hands the
136 * application over to it, replacing the pid it currently holds.
137 *
138 * Used when the pid we hold can no longer be confirmed to be this application - it has
139 * been recycled by an unrelated process, or it can no longer be read at all - but the
140 * application itself may well be running elsewhere. Unlike adoptRunningProcess() this does
141 * not require the application's pid to be unset.
142 *
143 * @param stalePid the pid the application is expected to hold; the handover is abandoned
144 * if it has changed in the meantime, so that a concurrent start always wins.
145 * @return the status to report, or nothing if no better process was found and the caller
146 * should stick with its own conclusion.
147 */
148 static std::optional<std::string>
149 rediscover(const Data_Structure::ApplicationInstancePtr& application,
150 StatusManager& statusManager,
151 int stalePid);
152 };
153
154} // namespace ScenarioManager::Exec
virtual std::string getStatus(Data_Structure::ApplicationInstancePtr application, StatusManager statusManager) override
Returns the status of an application.
virtual void startApplication(Data_Structure::ApplicationInstancePtr application, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false) override
Starts an application.
std::shared_ptr< ApplicationInstance > ApplicationInstancePtr