Init basesystem source codes.
[staging/basesystem.git] / video_in_hal / systemservice / system_manager / server / src / processlauncher / ProcessLauncher.cpp
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 ///////////////////////////////////////////////////////////////////////////////
18 /// \ingroup  tag_SystemManager
19 /// \brief    This file provides support for process launching and termination.
20 ///
21 ///////////////////////////////////////////////////////////////////////////////
22 #include <native_service/frameworkunified_framework_if.h>
23 #include <native_service/frameworkunified_multithreading.h>
24 #include <system_service/ss_templates.h>
25 #include <system_service/ss_string_maps.h>
26 #include <native_service/ns_plogger_if.h>
27 #include <string>
28
29 #include "ProcessLauncher.h"
30 #include "ss_sm_process_launcher_protocol.h"
31 #include "ss_sm_process_launcher.h"
32 #include "ss_sm_systemmanagerlog.h"
33 #include "ss_sm_signals.h"
34
35 CProcessLauncher::CProcessLauncher() {  // LCOV_EXCL_START 8: dead code
36   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
37 }
38 // LCOV_EXCL_STOP
39
40 CProcessLauncher::CProcessLauncher(void *) {
41 }
42
43 CProcessLauncher::~CProcessLauncher() {  // LCOV_EXCL_START 14: resident process end
44   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
45   m_mapOfProcesses.clear();
46 }
47 // LCOV_EXCL_STOP
48
49 EFrameworkunifiedStatus CProcessLauncher::PLTerminateModule(
50                              HANDLE hThread,
51                              T_ProcessLauncherTerminationResp *f_pTerminateRespData) {
52   EFrameworkunifiedStatus l_eStatus;
53   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
54
55   T_ProcessLauncherTerminationReq l_ModuleTerminateReq;
56
57   // LCOV_EXCL_BR_START 4:NSFW error case
58   if (eFrameworkunifiedStatusOK
59       != (l_eStatus = ReadMsg < T_ProcessLauncherTerminationReq > (hThread, l_ModuleTerminateReq, eSMRRetain))) {
60   // LCOV_EXCL_BR_STOP
61     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
62     LOG_ERROR("ReadMsg()");  // LCOV_EXCL_LINE 4:NSFW error case
63   } else {
64     // get pointer to the process object launched earlier
65     Process * l_pProcessPtr = m_mapOfProcesses[l_ModuleTerminateReq.path];  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
66
67     // Confirm that the process pointer for the module exists in the map
68     if (NULL != l_pProcessPtr) {  // LCOV_EXCL_BR_LINE 200: l_pProcessPtr must not be null
69       // check if process still exists
70       if (l_pProcessPtr->DoesProcessExist()) {
71         FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__,
72                " Terminating %s, PID: %d.", l_ModuleTerminateReq.path, l_pProcessPtr->GetProcessId());
73         // kill unresponsive process
74         l_pProcessPtr->KillProcess(SS_SM_ABORT_SIGNAL);
75
76         if (NULL != f_pTerminateRespData) {  // LCOV_EXCL_BR_LINE 200: f_pTerminateRespData must not be null
77           std::strcpy(f_pTerminateRespData->name,  // NOLINT
78                       l_ModuleTerminateReq.name);
79           std::strcpy(f_pTerminateRespData->path,  // NOLINT
80                       l_ModuleTerminateReq.path);
81           std::strcpy(f_pTerminateRespData->args,  // NOLINT
82                       l_ModuleTerminateReq.args);
83           f_pTerminateRespData->moduleIterator =
84                       l_ModuleTerminateReq.moduleIterator;
85           f_pTerminateRespData->groupIterator =
86                       l_ModuleTerminateReq.groupIterator;
87         }
88       } else {
89         FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, " Info: %s has already terminated.", l_ModuleTerminateReq.path);
90
91         l_eStatus = eFrameworkunifiedStatusServNotFound;
92       }
93       // remove process entry
94       m_mapOfProcesses.erase(l_ModuleTerminateReq.path);
95       // delete process object
96       delete l_pProcessPtr;  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
97     } else {  // LCOV_EXCL_BR_LINE 200: l_pProcessPtr will not be null
98       // LCOV_EXCL_START 200: l_pProcessPtr will not be null
99       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
100       l_eStatus = eFrameworkunifiedStatusDbRecNotFound;
101       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " Error: %s not in m_mapOfProcesses", l_ModuleTerminateReq.path);
102       // LCOV_EXCL_STOP
103     }
104   }
105   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
106   return l_eStatus;
107 }
108
109 EFrameworkunifiedStatus CProcessLauncher::PLOnCmdTerminateModule(HANDLE hThread) {
110   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
111   EFrameworkunifiedStatus l_eStatus;
112
113   T_ProcessLauncherTerminationResp l_TerminateRespData;
114   if (eFrameworkunifiedStatusOK == (l_eStatus = PLTerminateModule(hThread, &l_TerminateRespData))) {
115     // reply to System Manager about successful module termination
116     l_eStatus = FrameworkunifiedSendParent(hThread,
117                               ePLThrdCmd_TERMINATE_MODULE_RESP,
118                               sizeof(l_TerminateRespData),
119                               &l_TerminateRespData);
120     LOG_STATUS(l_eStatus, "FrameworkunifiedSendParent(ePLThrdCmd_TERMINATE_MODULE_RESP");  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
121   } else if (eFrameworkunifiedStatusServNotFound == l_eStatus) {  // Already terminated
122     FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, " Info. Module already terminated.");
123   } else {
124     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
125         " Error: PLTerminateModule(%s) errored: %d/'%s'",
126         l_TerminateRespData.name, l_eStatus, GetStr(l_eStatus).c_str());
127   }
128   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
129   return l_eStatus;
130 }
131
132 EFrameworkunifiedStatus CProcessLauncher::PLOnCmdModuleStatus(HANDLE hThread) {
133   return eFrameworkunifiedStatusOK;
134 }
135
136 VOID buildArgList(StringList& arg_list, PSTR args) {  // NOLINT
137   arg_list.clear();
138   char * pch = NULL;
139   pch = std::strtok(args, " ");
140   while (pch != NULL) {
141     arg_list.push_back(pch);
142     pch = std::strtok(NULL, " ");
143   }
144 }
145
146 EFrameworkunifiedStatus CProcessLauncher::PLLaunchModule(HANDLE hThread, T_ProcessLaunchResp &f_LaunchRespData) {
147   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
148   EFrameworkunifiedStatus                   l_eStatus;
149   Process                     *l_pProcessPtr = NULL;
150   T_ProcessLauncherLaunchReq   l_ModuleLaunchReq;
151
152   // LCOV_EXCL_BR_START 4:NSFW error case
153   if (eFrameworkunifiedStatusOK
154       != (l_eStatus = ReadMsg < T_ProcessLauncherLaunchReq > (hThread, l_ModuleLaunchReq))) {
155   // LCOV_EXCL_BR_STOP
156     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
157     LOG_ERROR("ReadMsg()");  // LCOV_EXCL_LINE 4:NSFW error case
158   } else {
159     FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__,
160             "Sending to Launcher name: %s, path: %s, args: %s, lmsk: %s, "
161                     "prio: %d ", l_ModuleLaunchReq.name,
162             l_ModuleLaunchReq.path, l_ModuleLaunchReq.args,
163             l_ModuleLaunchReq.logging_mask, l_ModuleLaunchReq.priority);
164
165     StringList args;
166     buildArgList(args, l_ModuleLaunchReq.args);  // LCOV_EXCL_BR_LINE 15: marco defined in ns_logger_if.h  // NOLINT(whitespace/line_length)
167
168     int log_mask_str_len = static_cast<int>(std::strlen(l_ModuleLaunchReq.logging_mask));
169     if (log_mask_str_len > 0) {
170       // Create mask argument to be passed to application.
171       // The argument must be of the form "-m 0x00000000,0x00000000,...", assuming n 32-bit mask values.
172       // The storage size of the argument must include one byte for the NULL termination character.
173       args.push_back("-m");
174       args.push_back(l_ModuleLaunchReq.logging_mask);
175       FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, " %s args: logging_mask: %s",
176               l_ModuleLaunchReq.path, l_ModuleLaunchReq.logging_mask);
177     } else {
178       FRAMEWORKUNIFIEDLOG(ZONE_PROC_LAUNCH_INFO, __FUNCTION__,
179               " '%s' has no logging_mask specified. Using compile time defaults.",
180               l_ModuleLaunchReq.path);
181     }
182
183     std::strcpy(f_LaunchRespData.name, l_ModuleLaunchReq.name);  // NOLINT Module queue name
184     std::strcpy(f_LaunchRespData.path, l_ModuleLaunchReq.path);  // NOLINT Module path and file name
185     std::strcpy(f_LaunchRespData.args, l_ModuleLaunchReq.args);  // NOLINT
186     f_LaunchRespData.moduleIterator = l_ModuleLaunchReq.moduleIterator;
187     f_LaunchRespData.groupIterator = l_ModuleLaunchReq.groupIterator;
188
189     // Process exists?  If not, re-launch the process and create a new map entry.
190     l_pProcessPtr = m_mapOfProcesses[l_ModuleLaunchReq.path];  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
191     if (NULL == l_pProcessPtr) {  // LCOV_EXCL_BR_LINE 200: l_pProcessPtr must not be null
192       FRAMEWORKUNIFIEDLOG(ZONE_PROC_LAUNCH_INFO, __FUNCTION__,
193               " '%s' is not in the module map. Creating new process.",
194               l_ModuleLaunchReq.name);
195
196       SS_String sPathAndFileName = l_ModuleLaunchReq.path;  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
197       l_pProcessPtr = new (std::nothrow) Process(l_ModuleLaunchReq.cpu_assign);  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
198
199       if (NULL == l_pProcessPtr) {  // LCOV_EXCL_BR_LINE 11::new operation failed
200         // LCOV_EXCL_START 11::new operation failed
201         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
202         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " Error: Process() returned NULL");
203         FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
204         return eFrameworkunifiedStatusThreadNotExist;
205         // LCOV_EXCL_STOP 11::new operation failed
206       }
207
208       const char* uname =
209               ('\0' == f_LaunchRespData.moduleIterator->unix_user_name[0]) ?
210                       NULL : &f_LaunchRespData.moduleIterator->unix_user_name[0];  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
211
212       l_pProcessPtr->CreateProcess(sPathAndFileName, "", l_ModuleLaunchReq.priority, args, uname);  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
213
214       FRAMEWORKUNIFIEDLOG(ZONE_PROC_LAUNCH_INFO, __FUNCTION__,
215               " Process Name: %s Process File: %s Pid: %d Is Alive: %s\n",
216               l_pProcessPtr->GetProcessName().data(),
217               l_pProcessPtr->GetExecutableFileName(),
218               l_pProcessPtr->GetProcessId(),
219               (l_pProcessPtr->DoesProcessExist() == FALSE) ? "No" : "Yes");
220
221       // Add the process in the map
222       m_mapOfProcesses[l_ModuleLaunchReq.path] = l_pProcessPtr;  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
223
224       // launch response
225       f_LaunchRespData.pid = l_pProcessPtr->GetProcessId();
226       f_LaunchRespData.priority = l_pProcessPtr->GetPriority();  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
227       l_eStatus = eFrameworkunifiedStatusOK;
228     } else {
229       // LCOV_EXCL_START 200: l_pProcessPtr must not be null
230       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
231       FRAMEWORKUNIFIEDLOG(ZONE_PROC_LAUNCH_INFO, __FUNCTION__,
232               " %s already in Process Map", l_ModuleLaunchReq.name);
233       // the module is already in the list. Send the response to system manager with PID 0x7FFFFFFF
234       f_LaunchRespData.pid = 0x7FFFFFFF;
235       f_LaunchRespData.priority = l_ModuleLaunchReq.priority;
236       l_eStatus = eFrameworkunifiedStatusOK;
237       // LCOV_EXCL_STOP
238     }
239   }
240
241   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
242   return l_eStatus;
243 }
244
245 EFrameworkunifiedStatus CProcessLauncher::PLOnCmdLaunchModule(HANDLE hThread) {
246   EFrameworkunifiedStatus l_eStatus;
247   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
248
249   l_eStatus = PLCmdLaunchModule(hThread, ePLThrdCmd_LAUNCH_MODULE_RESP, "ePLThrdCmd_LAUNCH_MODULE_RESP");  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
250   LOG_STATUS_IF_ERRORED(l_eStatus, " PLCmdLaunchModule(ePLThrdCmd_LAUNCH_MODULE_RESP)");  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
251
252   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
253   return l_eStatus;
254 }
255
256 EFrameworkunifiedStatus CProcessLauncher::PLOnCmdRelaunchModule(HANDLE hThread) {
257   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
258   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
259
260   // Terminate unresponsive module
261   CALL_AND_LOG_STATUS(PLTerminateModule(hThread));  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
262
263   l_eStatus = PLCmdLaunchModule(hThread, ePLThrdCmd_RELAUNCH_MODULE_RESP, "ePLThrdCmd_RELAUNCH_MODULE_RESP");  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
264   LOG_STATUS_IF_ERRORED(l_eStatus, "PLCmdLaunchModule(ePLThrdCmd_RELAUNCH_MODULE_RESP)");  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
265
266   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
267   return l_eStatus;
268 }
269
270 EFrameworkunifiedStatus CProcessLauncher::PLCmdLaunchModule(HANDLE hThread, UI_32 f_protocol_ID, std::string f_protocol_str) {
271   EFrameworkunifiedStatus l_eStatus;
272   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
273
274   T_ProcessLaunchResp l_LaunchRespData;
275   l_LaunchRespData.pid = 0;
276   if (eFrameworkunifiedStatusOK != (l_eStatus = PLLaunchModule(hThread, l_LaunchRespData))) {  // LCOV_EXCL_BR_LINE 4:NSFW error case
277     // LCOV_EXCL_START 4:NSFW error case
278     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
279     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
280             " Error: PLLaunchModule(%s, %s) errored: %d/'%s'",
281             l_LaunchRespData.name, f_protocol_str.c_str(), l_eStatus,
282             GetStr(l_eStatus).c_str());
283     // LCOV_EXCL_STOP 4:NSFW error case
284   } else {
285     l_eStatus = FrameworkunifiedSendParent(hThread, f_protocol_ID,
286             sizeof(T_ProcessLaunchResp), &l_LaunchRespData);
287
288     if (eFrameworkunifiedStatusOK != l_eStatus) {  // LCOV_EXCL_BR_LINE 4:NSFW error case
289       // LCOV_EXCL_START 4:NSFW error case
290       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
291       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
292               " Error: FrameworkunifiedSendParent( %s, %s ) errored: %d/'%s'",
293               l_LaunchRespData.name, f_protocol_str.c_str(), l_eStatus,
294               GetStr(l_eStatus).c_str());
295       // LCOV_EXCL_STOP 4:NSFW
296     }
297   }
298
299   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
300   return l_eStatus;
301 }
302
303 EFrameworkunifiedStatus CProcessLauncher::PLOnCmdStop(HANDLE hThread) {  // LCOV_EXCL_START 14: resident process end
304   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
305   return eFrameworkunifiedStatusOK;
306 }
307 // LCOV_EXCL_STOP
308
309 EFrameworkunifiedStatus CProcessLauncher::PLOnCmdStart(HANDLE hThread) {
310   return eFrameworkunifiedStatusOK;
311 }
312
313 EFrameworkunifiedStatus CProcessLauncher::PLOnCmdHeartbeatStatusReq(HANDLE hThread) {
314   FrameworkunifiedSendParent(hThread, ePLThrdCmd_THREAD_STATUS_RESP, 0, NULL);
315   return eFrameworkunifiedStatusOK;
316 }
317