Init basesystem source codes.
[staging/basesystem.git] / video_in_hal / systemservice / task_manager / server / src / pri_main.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 #include "pri_main.h"
18 #include <string.h>
19 #include <errno.h>
20 #include <pthread.h>
21 #include <sys/eventfd.h>
22 #include <stdlib.h>
23 #include <native_service/frameworkunified_dispatcher.h>
24 #include <system_service/ss_system_if.h>
25
26 #include "tskm_debug.h"
27 #include "tskm_comm.h"
28 #include "tskm_port_pf.h"
29 #include "tskm_port_subsys.h"
30 #include "tskm_util.h"
31
32
33
34 #define PRI_PROC_NAME_MAX 32
35
36 // Context
37 typedef struct {
38   T_PRIM_PRM prm;
39
40   TSKM_SVCID_t svcId;      // Set valid value by REQ_WAKEUP
41   char procName[PRI_PROC_NAME_MAX];
42   // State
43   TSKM_BOOL_t isExec;
44   T_SS_SM_START_DataStructType bootInfo;
45   T_SS_SM_START_ExtDataStructType extBootInfo; TSKM_BOOL_t isDynamic;
46   uint32_t wakeupStepDone;  // Executed local step
47   TSKM_BOOL_t shmDone;
48   uint32_t downStepDone;    // Executed local step
49   TSKM_BOOL_t isExitStart;
50
51 #define PRI_MONITOR_DEFAULT_TIMEOUT 50
52   uint32_t timeout;    // Service monitoring timeout period (valid only for the INI_Main type service)
53
54   // Resources
55   int connFd;       // TSKM communication socket
56   int nsFd;         // NSFW socket
57   int pipeFd[2];    // for exitDone
58   HANDLE hApp;      // appHandle
59 } PRI_CTX_t;
60
61 static PRI_CTX_t g_pri;
62
63 /*********************************************
64  *    Create shared memory
65  *********************************************/
66 TSKM_STATIC void shmMake(PRI_CTX_t* p_ctx) {
67   const PRIM_SHAREDATA_TBL* shmEntry;
68   for (shmEntry = p_ctx->prm.shmTbl; shmEntry->shmName[0] != '\0'; shmEntry++) {
69     int ret;
70     ret = tskm_pf_shmCreate(shmEntry->shmName, shmEntry->size, NULL);
71     if (ret != 0) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded
72       // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
73       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
74       TSKM_ASSERT(0);
75       goto ERROR;
76       // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded
77     }
78   }
79   p_ctx->shmDone = TSKM_TRUE;
80   return;
81
82   // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
83   ERROR:
84   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
85   tskm_pf_abort();
86   // LCOV_EXCL_STOP
87 }
88
89 /*********************************************
90  *    Call backup check CB
91  *********************************************/
92 TSKM_STATIC uint32_t wakeupExFuncCallback(PRI_CTX_t* p_ctx,
93                                           TSKM_EV_PRI_REQ_WAKEUP_PRM_t* p_prm) {
94   const PRIM_EXFUNC_TBL* funcEntry;
95   uint32_t maxStep = 0;
96
97   for (funcEntry = p_ctx->prm.wakeupExFuncTbl; funcEntry->localStep != 0;
98       funcEntry++) {
99     if (funcEntry->localStep == p_prm->localStep) {
100       funcEntry->func(funcEntry->prm);
101     }
102     maxStep = TSKM_MAX(maxStep, funcEntry->localStep);
103   }
104   return maxStep;
105 }
106
107 /*********************************************
108  *    Gradual startup request
109  *********************************************/
110 TSKM_STATIC void wakeupRequest(PRI_CTX_t* p_ctx,
111                                TSKM_EV_PRI_REQ_WAKEUP_PRM_t* p_prm) {
112   TSKM_EV_PRI_REQ_WAKEUP_PRM_t prm = *p_prm;
113   uint32_t max = 0;
114
115   // Execute step by step
116   for (prm.localStep = p_ctx->wakeupStepDone + 1;
117       (prm.localStep <= p_prm->localStep && prm.localStep < PRIM_STEPFORK_MAX);
118       prm.localStep++) {
119     max = wakeupExFuncCallback(p_ctx, &prm);
120   }
121
122   if (max <= p_prm->localStep) {
123     // Completed gradual startup
124     p_ctx->wakeupStepDone = PRIM_STEPFORK_MAX;
125   } else {
126     p_ctx->wakeupStepDone = p_prm->localStep;
127   }
128 }
129
130 /*********************************************
131  *    All startup requests
132  *********************************************/
133 TSKM_STATIC void allWakeup(PRI_CTX_t* p_ctx,
134                            TSKM_EV_PRI_REQ_WAKEUP_PRM_t* p_prm) {
135   if (!p_ctx->shmDone) {
136     shmMake(p_ctx);
137   }
138
139   if (p_ctx->wakeupStepDone < PRIM_STEPFORK_MAX) {
140     wakeupRequest(p_ctx, p_prm);
141   }
142 }
143
144 /*********************************************
145  *   Startup request handles
146  *********************************************/
147 TSKM_STATIC void wakeupRequestHandle(PRI_CTX_t* p_ctx,
148                                      TSKM_EV_PRI_REQ_WAKEUP_PRM_t* p_prm) {
149   TSKM_EVENT_INFO_t ev;
150   int ret;
151
152   bzero(&ev, sizeof(ev));
153
154   p_ctx->svcId = p_prm->svcId;
155   memcpy(&p_ctx->bootInfo, &p_prm->bootInfo, sizeof(p_ctx->bootInfo));
156   memcpy(&p_ctx->extBootInfo, &p_prm->extBootInfo, sizeof(p_ctx->extBootInfo));
157   p_ctx->isDynamic = p_prm->isDynamic;
158
159   if (p_prm->localStep == TSKM_LSTEP_ALL) {
160     allWakeup(p_ctx, p_prm);
161   } else if (p_prm->localStep == TSKM_LSTEP_LAST) {
162     wakeupRequest(p_ctx, p_prm);
163   } else if (p_prm->localStep == TSKM_LSTEP_SHM) {
164     shmMake(p_ctx);
165   } else {
166     wakeupRequest(p_ctx, p_prm);
167   }
168
169   ev.prm.resWakeup.isShmDone = p_ctx->shmDone;
170   ev.prm.resWakeup.isStepDone =
171       (p_ctx->wakeupStepDone >= PRIM_STEPFORK_MAX) ?
172       TSKM_TRUE :
173                                                      TSKM_FALSE;
174
175   // LCOV_EXCL_BR_START 6: Because it depends on the test order
176   if (ev.prm.resWakeup.isShmDone && ev.prm.resWakeup.isStepDone) {
177     // LCOV_EXCL_BR_STOP
178     ev.prm.resWakeup.isLast = TSKM_TRUE;
179   }
180
181   ev.event = TSKM_EV_PRI_RES_WAKEUP;
182   ev.errCode = TSKM_E_OK;
183   ret = tskm_sockSend(p_ctx->connFd, &ev);
184   if (ret <= 0) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded
185     // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
186     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
187     TSKM_ASSERT(0);
188     tskm_pf_abort();
189     // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded
190   }
191 }
192
193 /*********************************************
194  *    Gradual termination callback
195  *********************************************/
196 TSKM_STATIC uint32_t downExFuncCallback(PRI_CTX_t* p_ctx,
197                                         TSKM_EV_PRI_REQ_DOWN_PRM_t* p_prm) {
198   const PRIM_EXFUNC_TBL* funcEntry;
199   uint32_t maxStep = 0;
200
201   for (funcEntry = p_ctx->prm.downExFuncTbl; funcEntry->localStep != 0;
202       funcEntry++) {
203     if (funcEntry->localStep == p_prm->localStep) {
204       funcEntry->func(funcEntry->prm);
205     }
206     maxStep = TSKM_MAX(maxStep, funcEntry->localStep);
207   }
208   return maxStep;
209 }
210
211 /*********************************************
212  *    Gradual termination requests
213  *********************************************/
214 TSKM_STATIC void downRequest(PRI_CTX_t* p_ctx,
215                              TSKM_EV_PRI_REQ_DOWN_PRM_t* p_prm) {
216   TSKM_EV_PRI_REQ_DOWN_PRM_t prm = *p_prm;
217   uint32_t max = 0;
218
219   // Execute step by step
220   for (prm.localStep = p_ctx->downStepDone + 1;
221       (prm.localStep <= p_prm->localStep && prm.localStep < PRIM_ACCOFF_MAX);
222       prm.localStep++) {
223     max = downExFuncCallback(p_ctx, &prm);
224   }
225
226   if (max <= p_prm->localStep) {
227     p_ctx->downStepDone = PRIM_ACCOFF_MAX;  // Completed all steps
228   } else {
229     p_ctx->downStepDone = p_prm->localStep;
230   }
231 }
232
233 TSKM_STATIC void downRequestHandle(PRI_CTX_t* p_ctx,
234                                    TSKM_EV_PRI_REQ_DOWN_PRM_t* p_prm) {
235   TSKM_EVENT_INFO_t ev;
236   int ret;
237
238   bzero(&ev, sizeof(ev));
239
240   if (p_prm->localStep == TSKM_LSTEP_ALL || p_prm->localStep == TSKM_LSTEP_LAST) {
241     downRequest(p_ctx, p_prm);
242   } else if (p_prm->localStep == TSKM_LSTEP_SHM) {
243     TSKM_ASSERT(0);
244   } else if (p_prm->localStep == TSKM_LSTEP_BUPCHK) {
245     TSKM_ASSERT(0);
246   } else {
247     downRequest(p_ctx, p_prm);
248   }
249
250   if (p_ctx->downStepDone >= PRIM_ACCOFF_MAX) {
251     /* It is not notified when the last function is executed, and it is left to the exitDone.
252      TSKM_PRINTF(TSKM_LOG_DEBUG,"ACCOFF DONE");
253      ev.prm.resDown.isLast = TSKM_TRUE;
254      p_ctx->isExec = TSKM_FALSE;
255      ret =  tskm_sockSend(p_ctx->connFd,&ev);
256      if(ret <= 0){
257      TSKM_ASSERT(0);
258      tskm_pf_abort();
259      }
260      */
261   } else {
262     ev.event = TSKM_EV_PRI_RES_DOWN;
263     ev.errCode = TSKM_E_OK;
264     ret = tskm_sockSend(p_ctx->connFd, &ev);
265     if (ret <= 0) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded
266       // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
267       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
268       TSKM_ASSERT(0);
269       tskm_pf_abort();
270       // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded
271     }
272   }
273 }
274
275 /*********************************************
276  *  Termination completion notification to the TSKM 
277  *********************************************/
278 TSKM_STATIC void sendLastDoneRes(PRI_CTX_t* p_ctx) {
279   int ret;
280   TSKM_EVENT_INFO_t ev;
281
282   bzero(&ev, sizeof(ev));
283
284   ev.event = TSKM_EV_PRI_RES_DOWN;
285   ev.errCode = TSKM_E_OK;
286   ev.prm.resDown.isLast = TSKM_TRUE;
287   ret = tskm_sockSend(p_ctx->connFd, &ev);
288   if (ret <= 0) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded
289     // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
290     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
291     TSKM_ASSERT(0);
292     tskm_pf_abort();
293     // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded
294   }
295 }
296
297 /*********************************************
298  *  Call Touch CB
299  *********************************************/
300 TSKM_STATIC void touchService(PRI_CTX_t* p_ctx) {
301   char touchName[32];
302
303   if (p_ctx->isExitStart) {
304     // If termination has already begun, the system just processes as timeout for retrying not respond Touch
305     return;
306   }
307
308   p_ctx->prm.onTouch(p_ctx->hApp);
309
310   tskm_pf_mkTouchFileName(getpid(), touchName);
311
312   if ((access(touchName, F_OK) == 0)) {
313     // Synchronize by deleting files.
314     TSKM_PRINTF(TSKM_LOG_STATE, "del:%s", touchName);
315     unlink(touchName);
316   } else {
317     TSKM_ASSERT_PRINT(0, "%s", touchName);
318   }
319 }
320
321 /*********************************************
322  *  Call Debugdump CB
323  *********************************************/
324 TSKM_STATIC void callDebugDump(PRI_CTX_t* p_ctx) {
325   if (!p_ctx->prm.onDebugDump) {  // LCOV_EXCL_BR_LINE 6: As NULL checked by INI_Init
326     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
327     TSKM_ASSERT(0);  // LCOV_EXCL_LINE 6: As NULL checked by INI_Init
328   } else {
329     p_ctx->prm.onDebugDump(p_ctx->hApp);
330   }
331 }
332
333 /*********************************************
334  *  Call LowMemory detection
335  *********************************************/
336 TSKM_STATIC void callLowMem(PRI_CTX_t* p_ctx) {
337   if (!p_ctx->prm.onLowMem) {
338     TSKM_ASSERT(0);
339   } else if (!p_ctx->isExitStart) {
340     // Notify LowMemory only before starting terminating process
341     p_ctx->prm.onLowMem(p_ctx->hApp);
342   }
343 }
344
345 /*********************************************
346  *   Event handles
347  *********************************************/
348 TSKM_STATIC void eventHandle(PRI_CTX_t* p_ctx, TSKM_EVENT_INFO_t* p_ev) {
349   //Processing according to the request
350   switch (p_ev->event) {
351     case TSKM_EV_PRI_REQ_WAKEUP:
352       wakeupRequestHandle(p_ctx, &p_ev->prm.reqWakeup);
353       break;
354     case TSKM_EV_PRI_REQ_DOWN:
355       downRequestHandle(p_ctx, &p_ev->prm.reqDown);
356       break;
357     case TSKM_EV_PRI_REQ_TOUCH:
358       touchService(p_ctx);
359       break;
360     case TSKM_EV_PRI_REQ_DEBUGDUMP:
361       callDebugDump(p_ctx);
362       break;
363     case TSKM_EV_PRI_REP_LOWMEM:
364       callLowMem(p_ctx);
365       break;
366     default:
367       TSKM_ASSERT(0);
368       break;
369   }
370 }
371
372 /*********************************************
373  *   Initialize Context
374  *********************************************/
375 TSKM_STATIC void initCtx(T_PRIM_PRM* p_prm, PRI_CTX_t* p_ctx, int argc,
376                          char* argv[]) {
377   FrameworkunifiedDefaultCallbackHandler cbFuncs;
378
379   p_ctx->prm = *p_prm;
380
381   cbFuncs.onInitilization = p_ctx->prm.onInit;
382   cbFuncs.onDestroy = p_ctx->prm.onDestory;
383   cbFuncs.onDebugDump = p_ctx->prm.onDebugDump;
384   cbFuncs.onStart = FrameworkunifiedOnStart;
385   cbFuncs.onStop = FrameworkunifiedOnStop;
386   cbFuncs.createStateMachine = FrameworkunifiedCreateStateMachine;
387   cbFuncs.ssFrameworkInterface = FrameworkunifiedSSFrameworkInterface;
388
389   EFrameworkunifiedStatus taskmanagerRet;
390   taskmanagerRet = FrameworkunifiedCreateDispatcherWithoutLoop(p_ctx->prm.name, p_ctx->hApp, argc,
391                                           argv, &cbFuncs, FALSE);
392   if (eFrameworkunifiedStatusOK != taskmanagerRet) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded
393     // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
394     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
395     TSKM_ASSERT_PRINT(0, "%d", taskmanagerRet);
396     goto ERROR;
397     // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded
398   }
399
400   taskmanagerRet = FrameworkunifiedGetDispatcherFD(p_ctx->hApp, &p_ctx->nsFd);
401   if (taskmanagerRet != eFrameworkunifiedStatusOK) {
402     TSKM_ASSERT_PRINT(0, "%d", taskmanagerRet);
403     exit(EXIT_FAILURE);
404   }
405   p_ctx->connFd = tskm_cliSockConnect(TSKM_SOCKET_NAME);
406   if (p_ctx->connFd < 0) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded
407     // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
408     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
409     TSKM_ASSERT(0);
410     goto ERROR;
411     // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded
412   }
413   if (pipe(p_ctx->pipeFd) != 0) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded
414     // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
415     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
416     TSKM_ASSERT_ERRNO(0);
417     goto ERROR;
418     // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded
419   }
420
421   return;
422
423   // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
424   ERROR:
425   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
426   tskm_pf_abort();
427   // LCOV_EXCL_STOP
428 }
429
430 /*********************************************
431  *  Destroy context
432  *********************************************/
433 TSKM_STATIC void termCtx(PRI_CTX_t* p_ctx) {
434   if (p_ctx->shmDone) {  // LCOV_EXCL_BR_LINE 6: Since it has been set to True by INI_Handler and cannot be changed
435     const PRIM_SHAREDATA_TBL* shmEntry = p_ctx->prm.shmTbl;
436     for (shmEntry = p_ctx->prm.shmTbl; shmEntry->shmName[0] != '\0';
437         shmEntry++) {
438       TSKM_ASSERT(0 == tskm_pf_shmDelete(shmEntry->shmName));  // LCOV_EXCL_BR_LINE 8: For processing in which only return value 0 is set
439     }
440   }
441
442   if (p_ctx->connFd > 0) {  // LCOV_EXCL_BR_LINE 6: For processing in which only return value 0 is set
443     tskm_sockDestory(p_ctx->connFd);
444   }
445
446   EFrameworkunifiedStatus taskmanagerRet;
447   taskmanagerRet = FrameworkunifiedDestroyDispatcherWithoutLoop(p_ctx->hApp);
448   TSKM_ASSERT(taskmanagerRet == eFrameworkunifiedStatusOK);
449
450   if (p_ctx->isDynamic) {
451     TSKM_PRINTF(TSKM_LOG_STATE, "EXIT %s", p_ctx->procName);
452   } else {
453     // Hung up running services to prevent adversely affecting to system termination processing during process termination processing
454     sleep(TSKM_CFG_WAIT_SHUTDOWN);
455   }
456 }
457
458 /*******************************************************************
459  *    Initialize PRI context
460  *******************************************************************/
461 void pri_init(T_PRIM_PRM* p_prm, int argc, char* argv[], int *fdNum,
462               int fdlist[INI_FD_MAX]) {
463   int ret = 0;
464   PRI_CTX_t* p_ctx = &g_pri;
465
466   strncpy(p_ctx->procName, basename(argv[0]), sizeof(p_ctx->procName) - 1);
467
468   ret = tskm_pf_procInit();
469   if (ret != 0) {  // LCOV_EXCL_BR_LINE 6: Return value of 0 only
470     // LCOV_EXCL_START 6: Return value of 0 only
471     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
472     TSKM_ASSERT(0);
473     goto ERROR;
474     // LCOV_EXCL_STOP 6: Return value of 0 only
475   }
476
477   ret = tskm_comm_procInit();
478   if (ret != 0) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded
479     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
480     TSKM_ASSERT(0);
481     goto ERROR;
482     // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded
483   }
484
485   initCtx(p_prm, p_ctx, argc, argv);
486
487   *fdNum = 3;
488   fdlist[0] = p_ctx->connFd;
489   fdlist[1] = p_ctx->pipeFd[0];
490   fdlist[2] = p_ctx->nsFd;
491
492   p_ctx->svcId = TSKM_SVCID_NONE;
493   p_ctx->isExec = TSKM_TRUE;
494
495   p_ctx->bootInfo.startupReason = epswfINVALID;
496   p_ctx->bootInfo.isUserModeOn = FALSE;
497   p_ctx->bootInfo.dataResetMode = e_SS_SM_DATA_RESET_MODE_NONE;
498   p_ctx->bootInfo.securityStatus = epsssINVALID;
499   p_ctx->bootInfo.wakeupType = epsstINVALID;
500   p_ctx->bootInfo.dramBackupStatus = e_SS_SM_DRAM_BACKUP_UNSET;
501   p_ctx->bootInfo.resetStatus = e_SS_SM_RESET_STATUS_UNSET;
502
503   memset(&p_ctx->extBootInfo, 0, sizeof(p_ctx->extBootInfo));
504
505   p_ctx->timeout = PRI_MONITOR_DEFAULT_TIMEOUT;
506
507   return;
508   // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
509   ERROR:
510   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
511   tskm_pf_abort();  // ABORT
512 // LCOV_EXCL_STOP
513 }
514
515 /*******************************************************************
516  *    Primary library handler
517  *******************************************************************/
518 BOOL pri_handler(fd_set* p_fds) {
519   PRI_CTX_t* p_ctx = &g_pri;
520
521   if (FD_ISSET(p_ctx->connFd, p_fds)) {
522     int ret;
523     TSKM_EVENT_INFO_t ev;
524     ret = tskm_sockRcv(p_ctx->connFd, &ev);
525     // LCOV_EXCL_BR_START 5: True condition is checked in Death tests, but not reflected in coverage and excluded
526     if (ret > 0) {
527     // LCOV_EXCL_BR_STOP
528       eventHandle(p_ctx, &ev);
529     } else {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded
530       // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
531       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
532       TSKM_ASSERT(0);
533       goto ERROR;
534       // LCOV_EXCL_STOP
535     }
536   }
537
538   if (FD_ISSET(p_ctx->pipeFd[0], p_fds)) {
539     // only use exitDone
540     uint32_t tmp;
541     TSKM_ASSERT(sizeof(tmp) == read(p_ctx->pipeFd[0], &tmp, sizeof(tmp)));
542     TSKM_ASSERT(p_ctx->downStepDone == PRIM_ACCOFF_MAX);  // Check if all exit functions are complete
543     if (p_ctx->isDynamic) {
544       // A nonresident service completes its termination processing by terminating the process (because the SIGNAL will overtake the sockets)
545     } else {
546       // The resident service completes termination processing with a termination notice (Do not terminate processes to reduce the impact on system termination)
547       sendLastDoneRes(p_ctx);
548     }
549     p_ctx->isExec = TSKM_FALSE;
550   }
551
552   if (FD_ISSET(p_ctx->nsFd, p_fds)) {
553     FrameworkunifiedDispatchProcessWithoutLoop(p_ctx->hApp);
554   }
555   return p_ctx->isExec;
556
557   // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
558   ERROR:
559   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
560   tskm_pf_abort();  // ABORT
561   return 0;
562 // LCOV_EXCL_STOP
563 }
564
565 /*******************************************************************
566  *    Process termination
567  *******************************************************************/
568 void pri_term(void) {
569   PRI_CTX_t* p_ctx = &g_pri;
570   termCtx(p_ctx);
571 }
572
573 /*******************************************************************
574  *    Service Monitoring Status Setting
575  *******************************************************************/
576 int pri_setMonitorState(BOOL bIsRun, uint32_t timeout) {
577   PRI_CTX_t* p_ctx = &g_pri;
578   int ret = INI_SUCCESS;
579
580   if (TSKM_SVCID_NONE == p_ctx->svcId) {
581     // Ignore requests until svcId is acquired
582   } else if ((TRUE == bIsRun) && (0 == timeout)) {
583     // When RUN is specified with timeout = 0, monitoring is disabled
584   } else {
585     ret = tskm_comm_setSvcWatchState(p_ctx->svcId, bIsRun, timeout);
586     if (INI_SUCCESS != ret) {
587       TSKM_ASSERT(0);
588     }
589   }
590
591   return ret;
592 }
593
594 /*******************************************************************
595  *    MAIN function
596  *******************************************************************/
597 int pri_main(T_PRIM_PRM* p_prm, int argc, char* argv[]) {
598   int mainRet = -1;
599   int fdlist[INI_FD_MAX];
600   int fdNum;
601   int ii;
602   BOOL isExec = TRUE;
603
604   pri_init(p_prm, argc, argv, &fdNum, fdlist);
605
606   while (isExec) {
607     PRI_CTX_t* p_ctx = &g_pri;
608     int maxFd = 0;
609     fd_set fds;
610     int ret;
611
612     FD_ZERO(&fds);
613
614     for (ii = 0; ii < fdNum; ii++) {
615       FD_SET(fdlist[ii], &fds);
616       maxFd = TSKM_MAX(fdlist[ii], maxFd);
617     }
618
619     TSKM_ASSERT(INI_SUCCESS == pri_setMonitorState(FALSE, 0));
620     ret = select(maxFd + 1, &fds, NULL, NULL, NULL);
621     TSKM_ASSERT(INI_SUCCESS == pri_setMonitorState(TRUE, p_ctx->timeout));
622     if (ret < 1) {
623       if (errno != EINTR) {
624         TSKM_ASSERT(0);
625       }
626       continue;
627     }
628
629     isExec = pri_handler(&fds);
630   }
631
632   mainRet = 0;
633
634   pri_term();
635   return mainRet;
636 }
637
638 /*******************************************************************
639  *    Termination request
640  *******************************************************************/
641 void pri_exitStart(void *rsv) {
642   int ret;
643   PRI_CTX_t* p_ctx = &g_pri;
644   TSKM_EVENT_INFO_t ev;
645
646   bzero(&ev, sizeof(ev));
647   p_ctx->isExitStart = TRUE;
648   ev.event = TSKM_EV_PRI_REQ_EXIT;
649   ev.errCode = TSKM_E_OK;
650
651   ret = tskm_sockSend(p_ctx->connFd, &ev);
652   if (ret <= 0) {  // LCOV_EXCL_BR_LINE 6: The caller's external API does not execute the second or subsequent processing and cannot be checked
653     TSKM_ASSERT(0);
654     goto ERROR;
655   }
656   return;
657   // LCOV_EXCL_START 6: The caller's external API does not execute the second or subsequent processing and cannot be checked
658   ERROR:
659   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
660   tskm_pf_abort();
661   // LCOV_EXCL_STOP
662 }
663
664 void pri_exitDone(int status) {
665   PRI_CTX_t* p_ctx = &g_pri;
666   uint32_t l_status = (uint32_t) status;
667
668   // LCOV_EXCL_BR_START 6: The caller's external API does not execute the second or subsequent processing and cannot be checked
669   if (p_ctx->pipeFd[1] > 0) {
670   // LCOV_EXCL_BR_STOP
671     // LCOV_EXCL_START 6: The caller's external API does not execute the second or subsequent processing and cannot be checked
672     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
673     TSKM_ASSERT_ERRNO(
674         write(p_ctx->pipeFd[1], &l_status, sizeof(l_status))
675             == sizeof(l_status));
676     // LCOV_EXCL_STOP
677   } else {
678     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
679     TSKM_ASSERT(0);  // LCOV_EXCL_LINE 6: The caller's external API does not execute the second or subsequent processing and cannot be checked
680   }
681 }
682
683 /*******************************************************************
684  *    Event completion notification at startup
685  *******************************************************************/
686 int32_t pri_stepForkComp(uint64_t id) {
687   int ret;
688   PRI_CTX_t* p_ctx = &g_pri;
689   TSKM_EVENT_INFO_t ev;
690
691   bzero(&ev, sizeof(ev));
692   ev.event = TSKM_EV_PRI_REP_WAKEUP_COMP;
693   ev.errCode = TSKM_E_OK;
694   ev.prm.repWakeupComp.compId = id;
695   ret = tskm_sockSend(p_ctx->connFd, &ev);
696   if (ret <= 0) {
697     TSKM_ASSERT(0);
698     goto ERROR;
699   }
700   return INI_SUCCESS;
701   ERROR: return INI_FALSE;
702 }
703
704 /*******************************************************************
705  *    Event completion notification at termination
706  *******************************************************************/
707 int32_t pri_accOffComp(uint64_t id) {
708   int ret;
709   PRI_CTX_t* p_ctx = &g_pri;
710   TSKM_EVENT_INFO_t ev;
711
712   bzero(&ev, sizeof(ev));
713
714   ev.event = TSKM_EV_PRI_REP_DOWN_COMP;
715   ev.errCode = TSKM_E_OK;
716   ev.prm.repDownComp.compId = id;
717   ret = tskm_sockSend(p_ctx->connFd, &ev);
718   if (ret <= 0) {
719     TSKM_ASSERT(0);
720     goto ERROR;
721   }
722   return INI_SUCCESS;
723   ERROR: return INI_FALSE;
724 }
725
726 /*******************************************************************
727  *    Get private info
728  *******************************************************************/
729 void*
730 pri_getPrivate() {
731   PRI_CTX_t* p_ctx = &g_pri;
732   return p_ctx->prm.priv;
733 }
734
735 /*******************************************************************
736  *    Get app-handle
737  *******************************************************************/
738 HANDLE pri_getHandle() {
739   PRI_CTX_t* p_ctx = &g_pri;
740   return p_ctx->hApp;
741 }
742
743 /*******************************************************************
744  *    Service monitoring status setting timeout setting
745  *******************************************************************/
746 int32_t pri_setMonitorTimeout(uint32_t timeout) {
747   PRI_CTX_t* p_ctx = &g_pri;
748   p_ctx->timeout = timeout;
749   return INI_SUCCESS;
750 }
751
752 /*******************************************************************
753  *    Get boot info
754  *******************************************************************/
755 int32_t pri_getBootInfo(T_SS_SM_START_DataStructType *info) {
756   PRI_CTX_t* p_ctx = &g_pri;
757
758   if (p_ctx->bootInfo.startupReason == epswfINVALID) {
759     TSKM_ASSERT(0);
760     return INI_FALSE;
761   }
762
763   *info = p_ctx->bootInfo;
764
765   return INI_SUCCESS;
766 }
767
768 /*******************************************************************
769  *    Get extended boot info
770  *******************************************************************/
771 int32_t pri_getExtBootInfo(T_SS_SM_START_ExtDataStructType *info) {
772   PRI_CTX_t* p_ctx = &g_pri;
773
774   if (p_ctx->bootInfo.startupReason == epswfINVALID) {
775     TSKM_ASSERT(0);
776     return INI_FALSE;
777   }
778
779   *info = p_ctx->extBootInfo;
780
781   return INI_SUCCESS;
782 }
783
784 /*******************************************************************
785  *    DebugDump response
786  *******************************************************************/
787 void pri_sendDebugDumpRes(const char *buf) {  // LCOV_EXCL_START 7: Debugging code
788   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
789   int ret;
790   PRI_CTX_t* p_ctx = &g_pri;
791   TSKM_EVENT_INFO_t ev;
792   TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t *p_prm;
793
794   ev.event = TSKM_EV_PRI_RES_DEBUGDUMP;
795   ev.errCode = TSKM_E_OK;
796   ev.hasExtend = TSKM_TRUE;
797
798   ev.extendPrm = malloc(sizeof(TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t));
799   if (!ev.extendPrm) {
800     TSKM_ASSERT(0);
801     goto ERROR;
802   }
803
804   ev.extendSize = sizeof(TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t);
805
806   p_prm = (TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t *) ev.extendPrm;  // NOLINT (readability/casting)
807   snprintf(p_prm->dumpMsg, TSKM_EV_DEBUGDUMP_SIZE, "%s", buf);
808
809   ret = tskm_sockSend(p_ctx->connFd, &ev);
810   if (ret <= 0) {
811     TSKM_ASSERT(0);
812   }
813
814   ERROR: return;
815 }
816 // LCOV_EXCL_STOP
817 /*************************************************
818  * Empty functions implemented for building software
819  **************************************************/
820 EFrameworkunifiedStatus FrameworkunifiedOnStart(HANDLE hApp) {
821   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
822   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
823   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
824   return l_eStatus;
825 }
826 EFrameworkunifiedStatus FrameworkunifiedOnStop(HANDLE hApp) {
827   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
828   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
829   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
830   return l_eStatus;
831 }
832
833 EFrameworkunifiedStatus FrameworkunifiedCreateStateMachine(HANDLE hApp) {  // LCOV_EXCL_START 6: Because the condition cannot be set
834   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
835   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
836   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
837   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
838   return l_eStatus;
839 }
840 // LCOV_EXCL_STOP