2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "system_service/tskm_svc.h"
20 #include <sys/inotify.h>
23 #include <native_service/ns_np_service_if.h>
26 #include "tskm_debug.h"
27 #include "tskm_util.h"
28 #include "tskm_port_pf.h"
29 #include "tskm_port_subsys.h"
30 #include "tskm_comm.h"
33 /*********************************************************
34 * Is the target event of the service handler?
36 *********************************************************/
37 TSKM_STATIC TSKM_BOOL_t isSvcEvent(const TSKM_EVENT_INFO_t* p_ev) {
38 switch (p_ev->event) {
39 case TSKM_EV_PRI_REP_CONNECT:
40 case TSKM_EV_PRI_REP_DISCONNECT:
41 case TSKM_EV_PRI_RES_WAKEUP:
42 case TSKM_EV_PRI_RES_DOWN:
43 case TSKM_EV_PRI_RES_DEBUGDUMP:
44 case TSKM_EV_PRI_REQ_EXIT:
45 case TSKM_EV_SVC_REP_TERM:
54 /*********************************************************
56 *********************************************************/
57 TSKM_STATIC TSKM_SVC_CTX_t*
58 getSvcCtxBySvcId(TSKM_SVCS_CTX_t* p_svcs, TSKM_SVCID_t svcId) {
61 for (ii = 0; ii < p_svcs->svcNum; ii++) {
62 if (p_svcs->svcList[ii].attr->svcId == svcId) {
63 return &p_svcs->svcList[ii];
70 /*********************************************************
72 *********************************************************/
73 TSKM_STATIC TSKM_SVC_CTX_t*
74 getSvcCtxByPid(TSKM_SVCS_CTX_t* p_svcs, pid_t pid) {
77 for (ii = 0; ii < p_svcs->svcNum; ii++) {
78 if (p_svcs->svcList[ii].pid == pid) {
79 return &p_svcs->svcList[ii];
85 /*********************************************************
87 *********************************************************/
88 TSKM_STATIC TSKM_SVC_CTX_t*
89 getSvcCtxByName(TSKM_SVCS_CTX_t* p_svcs, const char *p_name) { // LCOV_EXCL_START 6: Because the condition cannot be set
90 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
93 for (ii = 0; ii < p_svcs->svcNum; ii++) {
95 == strncmp(p_svcs->svcList[ii].attr->name, p_name,
96 strlen(p_svcs->svcList[ii].attr->name))) {
97 return &p_svcs->svcList[ii];
103 /*********************************************************
104 * Issuing a start request to the service
105 *********************************************************/
106 TSKM_STATIC TSKM_ERR_t wakeupRequest(TSKM_SVC_CTX_t* p_svc,
107 TSKM_GSTEP_REQ_INFO_t* p_req) {
108 TSKM_EVENT_INFO_t ev;
110 bzero(&ev, sizeof(ev));
112 ev.event = TSKM_EV_PRI_REQ_WAKEUP;
113 ev.errCode = TSKM_E_OK;
114 ev.prm.reqWakeup.svcId = p_svc->attr->svcId;
115 ev.prm.reqWakeup.localStep = p_req->localStep;
116 ev.prm.reqWakeup.isDynamic =
117 (p_svc->attr->lifeCycle == TSKM_SVC_LC_DYNAMIC) ? TSKM_TRUE : TSKM_FALSE;
118 // Since there is no startup in the P_CWORD72_ but only communication in the ALL/LAST,
119 // the startup information is optimized including the startup information in the communication of the WakeupRequest.
120 memcpy(&ev.prm.reqWakeup.bootInfo, &p_svc->bootInfo,
121 sizeof(ev.prm.reqWakeup.bootInfo));
122 memcpy(&ev.prm.reqWakeup.extBootInfo, &p_svc->extBootInfo,
123 sizeof(ev.prm.reqWakeup.extBootInfo));
125 ret = tskm_sockSend(p_svc->connFd, &ev);
131 p_svc->state = TSKM_SVC_WAKEUP;
134 ERROR: return TSKM_E_NG;
137 /*********************************************************
138 * Touch services and extend EXIT timeouts
139 *********************************************************/
140 TSKM_STATIC TSKM_ERR_t reqTouch(TSKM_SVC_CTX_t* p_svc) {
141 #define TSKM_BUF_LEN ( 4 * ( sizeof(struct inotify_event) ) ) /* read size */
142 TSKM_ERR_t funcRet = TSKM_E_NG;
143 char touchFileName[32];
144 BOOL isNeedRetry = FALSE;
146 int iFd = p_svc->iFd;
149 TSKM_EVENT_INFO_t ev;
151 bzero(&ev, sizeof(ev));
153 // Create monitoring files
154 tskm_pf_mkTouchFileName(p_svc->pid, touchFileName);
155 if (0 != tskm_pf_touch(touchFileName)) {
159 // Synchronize by iNortify
160 wd = inotify_add_watch(iFd, touchFileName, IN_DELETE_SELF);
162 TSKM_ASSERT_ERRNO(0);
166 // Send Touch request
167 ev.event = TSKM_EV_PRI_REQ_TOUCH;
168 ev.errCode = TSKM_E_OK;
169 ret = tskm_sockSend(p_svc->connFd, &ev);
171 // Immediately after the nonresident service process terminates, since the TaskManager service status is other than DORMANT
172 // (mainly DOWN), the socket may be discarded and communication may fail, so retry
173 funcRet = TSKM_E_RETRY;
174 TSKM_PRINTF(TSKM_LOG_WARN, "ret = %d", ret);
178 // Wait for Touch completion
184 struct timeval timeout = { 0 };
185 timeout.tv_sec = TSKM_CFG_TOUCH_TIMEOUT;
190 ret = select(maxFd + 1, &fds, NULL, NULL, &timeout);
192 TSKM_ASSERT_PRINT(0, "TIMEOUT:%s", touchFileName); // Timeout occurs
195 } else if (ret < 1) {
196 if (errno == EINTR) {
204 if (FD_ISSET(iFd, &fds)) {
206 uint8_t buf[TSKM_BUF_LEN];
208 length = static_cast<int>(read(iFd, buf, TSKM_BUF_LEN));
210 TSKM_ASSERT_ERRNO(0);
213 struct inotify_event *event = (struct inotify_event *) buf;
214 if (event->mask & IN_DELETE_SELF) {
215 TSKM_PRINTF(TSKM_LOG_STATE, "TouchOK");
217 // When a file is deleted, the association with the monitoring target is automatically released and inotify_rm_watch is no longer needed.
220 TSKM_ASSERT_PRINT(0, "%x", event->mask);
226 funcRet = TSKM_E_RETRY;
232 TSKM_ASSERT_ERRNO(0 == inotify_rm_watch(iFd, wd))
235 if (access(touchFileName, F_OK) == 0) {
237 unlink(touchFileName);
243 /*********************************************************
244 * Availability Monitoring Callbacks for Services
245 *********************************************************/
246 EFrameworkunifiedStatus OnSvcAvailability(HANDLE hApp) { // LCOV_EXCL_START 6: Because the condition cannot be set
247 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
248 PCSTR availabilityName;
249 TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx();
250 TSKM_SVC_CTX_t* p_svc;
252 availabilityName = FrameworkunifiedGetLastNotification(hApp);
254 std::string str = availabilityName;
256 // unsigned int position;
257 // if (std::string::npos != (position = static_cast<unsigned int>(str.find("/Availability", 0)))) {
259 if (0 <= (position = str.find("/Availability", 0))) {
260 str.erase(position, position + strlen("/Availability"));
263 p_svc = getSvcCtxByName(&p_main->svcs, str.c_str());
265 p_svc->isAvailable = FrameworkunifiedIsServiceAvailable(hApp) ? TSKM_TRUE : TSKM_FALSE;
266 TSKM_PRINTF(TSKM_LOG_SVCSTATE, "%s Availability %s", p_svc->attr->name,
267 (p_svc->isAvailable == TSKM_TRUE) ? "TRUE" : "FALSE");
270 return eFrameworkunifiedStatusOK;
273 /*********************************************************
274 * Starting Availability Monitoring of Services
275 *********************************************************/
276 TSKM_STATIC TSKM_ERR_t startWatchAvailability(TSKM_SVC_CTX_t* p_svc) {
277 TSKM_ERR_t funcRet = TSKM_E_OK;
279 // LCOV_EXCL_BR_START 8: Since the condition is checked by the caller, it is not true.
280 if (p_svc->attr->type == TSKM_SVC_TYPE_UNKNONW) {
282 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
283 p_svc->isAvailable = TSKM_TRUE; // LCOV_EXCL_LINE 8: Since the condition is checked by the caller, it is not true.
285 EFrameworkunifiedStatus taskmanagerStatus;
286 TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx();
287 SS_String availabilityName = p_svc->attr->name;
289 availabilityName.append("/Availability");
291 taskmanagerStatus = FrameworkunifiedSubscribeNotificationWithCallback(p_main->hApp,
292 availabilityName.c_str(),
294 if (eFrameworkunifiedStatusOK != taskmanagerStatus) {
303 /*********************************************************
304 * Service startup sub
305 *********************************************************/
306 void svcExec_Process(TSKM_SVC_CTX_t* p_svc) {
309 if (p_svc->attr->type == TSKM_SVC_TYPE_NATIVE) {
310 p_svc->state = TSKM_SVC_WAITCONNECT;
311 TSKM_PRINTF(TSKM_LOG_DEBUG, "[ST:%d] WAIT_EXEC", p_svc->pid);
312 funcRet = startWatchAvailability(p_svc);
313 if (TSKM_E_OK != funcRet) {
315 p_svc->isAvailable = TSKM_TRUE;
318 p_svc->state = TSKM_SVC_RUNNING;
319 TSKM_PRINTF(TSKM_LOG_SVCSTATE, "[ST:%d] RUN", p_svc->pid);
320 p_svc->isAvailable = TSKM_TRUE;
325 /*********************************************************
326 * Service startup main
327 *********************************************************/
328 TSKM_STATIC TSKM_ERR_t svcExec(TSKM_SVC_CTX_t* p_svc) {
329 TSKM_ERR_t funcRet = TSKM_E_NG;
332 if (p_svc == NULL) { // LCOV_EXCL_BR_LINE 6:double check
333 // LCOV_EXCL_START 6: double check
334 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
340 if (p_svc->state == TSKM_SVC_DISABLE) {
341 // Prohibited startup
344 } else if (p_svc->state == TSKM_SVC_WAITCONNECT) {
346 } else if (p_svc->state != TSKM_SVC_DORMANT) {
348 funcRet = reqTouch(p_svc);
349 if (TSKM_E_OK != funcRet) {
350 TSKM_PRINTF(TSKM_LOG_WARN, "funcRet = %d", funcRet);
356 pid = tskm_pf_createProc(p_svc->attr);
361 TSKM_PRINTF(TSKM_LOG_STATE, "EXEC %s:%d", p_svc->attr->name, pid);
364 p_svc->waitReqCnt = 0;
367 svcExec_Process(p_svc);
370 ERROR: return funcRet;
373 /*********************************************************
374 * Issuing a start request to the service
375 *********************************************************/
376 TSKM_STATIC TSKM_ERR_t svcWakeupRequest(TSKM_SVC_CTX_t* p_svc,
377 TSKM_GSTEP_REQ_INFO_t* p_req) {
378 if (p_svc == NULL || p_svc->state == TSKM_SVC_DISABLE) { // LCOV_EXCL_BR_LINE 6: Since this function has always been called after checking // NOLINT(whitespace/line_length)
379 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
380 return TSKM_E_STATE; // LCOV_EXCL_LINE 6: Since this function has always been called after checking
381 } else if (p_svc->state == TSKM_SVC_WAITCONNECT) {
382 // Remember it once and issue a request when the CONNECT completes.
383 p_svc->request[p_svc->waitReqCnt] = *p_req;
387 tskmRet = wakeupRequest(p_svc, p_req);
392 ERROR: return TSKM_E_NG;
395 /*********************************************************
396 * Service reboot processing
397 *********************************************************/
398 TSKM_STATIC TSKM_ERR_t svcErrTermPost(TSKM_SVC_CTX_t* p_svc) {
399 TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx();
401 TSKM_PRINTF(TSKM_LOG_SYSTEMDATA, "ERR TERM SVC(%s:%d)", p_svc->attr->name,
404 if (p_svc->attr->lifeCycle == TSKM_SVC_LC_ALWAYS || (p_svc->errTermCnt > p_svc->attr->retryCnt && (uint32_t) -1 != p_svc->attr->retryCnt)) { // NOLINT(whitespace/line_length)
405 TSKM_ERROR_REBOOT_t rebootInfo;
408 memset(&rebootInfo, 0, sizeof(TSKM_ERROR_REBOOT_t));
409 rebootInfo.type = TSKM_ERROR_REBOOT_NORMAL;
410 snprintf(rebootInfo.log.messageStr, TSKM_LOGGING_MSG_STR_SIZE,
411 "TaskManager:SVC ErrTerm");
412 tskm_sub_reboot(&rebootInfo);
414 TSKM_LOGGING_INFO_t logInfo;
415 logInfo.type = TSKM_LOGGING_TYPE_MODULE_LOGS;
417 snprintf(logInfo.messageStr, TSKM_LOGGING_MSG_STR_SIZE,
418 "TaskManager:SVC ErrTerm");
419 tskm_sub_logging(&logInfo);
421 if (p_svc->attr->lifeCycle == TSKM_SVC_LC_ALWAYS_RECOVERABLE) {
423 TSKM_GSTEP_REQ_INFO_t req = { 0 };
425 ret = svcExec(p_svc);
427 if (TSKM_E_OK != ret) {
428 TSKM_ASSERT_PRINT(0, "ret = %d", ret);
430 } else if (p_svc->state == TSKM_SVC_WAITCONNECT) {
431 // In the state waiting for execution
432 req.svcId = p_svc->attr->svcId;
433 req.localStep = TSKM_LSTEP_ALL;
434 ret = svcWakeupRequest(p_svc, &req);
435 if (TSKM_E_OK != ret) {
436 TSKM_ASSERT_PRINT(0, "ret = %d", ret);
444 ERROR: return TSKM_E_NG;
447 /*********************************************************
449 * ret:TRUE SVC status changed
450 * ret:FALSE SVC status not changed
451 *********************************************************/
452 TSKM_STATIC TSKM_BOOL_t connectHandle(TSKM_SVC_CTX_t* p_svc,
453 const TSKM_EVENT_INFO_t* p_inEv) {
456 TSKM_ASSERT(p_svc->state == TSKM_SVC_WAITCONNECT);
458 p_svc->connFd = p_inEv->prm.repConnect.connFd;
459 p_svc->state = TSKM_SVC_WAKEUP;
460 TSKM_PRINTF(TSKM_LOG_DEBUG, "[ST:%d] WAKEUP", p_svc->pid);
462 p_svc->waitResCnt = 0;
464 if (p_svc->waitReqCnt) {
465 for (ii = 0; ii < p_svc->waitReqCnt; ii++) {
466 TSKM_ASSERT(TSKM_E_OK == wakeupRequest(p_svc, &p_svc->request[ii]));
468 p_svc->waitReqCnt = 0;
474 /*********************************************************
475 * Disconnection handler
476 * ret:TRUE SVC status changed
477 * ret:FALSE SVC status not changed
478 *********************************************************/
479 TSKM_STATIC TSKM_BOOL_t disConnectHandle(TSKM_SVC_CTX_t* p_svc,
480 const TSKM_EVENT_INFO_t* p_inEv) {
486 /*********************************************************
487 * Response handler for the activation request
488 * ret:TRUE SVC status changed
489 * ret:FALSE SVC status not changed
490 *********************************************************/
491 TSKM_STATIC TSKM_BOOL_t resWakeupHandle(TSKM_SVC_CTX_t* p_svc,
492 const TSKM_EVENT_INFO_t* p_inEv) {
493 TSKM_ASSERT(p_svc->state == TSKM_SVC_WAKEUP);
494 TSKM_ASSERT(p_svc->waitResCnt > 0);
495 TSKM_BOOL_t isStateChg = TSKM_FALSE;
497 if (p_svc->isShmDone == TSKM_FALSE && p_inEv->prm.resWakeup.isShmDone) {
498 p_svc->isShmDone = TSKM_TRUE;
499 isStateChg = TSKM_TRUE;
500 TSKM_PRINTF(TSKM_LOG_SVCSTATE, "%s:SHM DONE", p_svc->attr->name);
502 if (p_svc->isStepDone == TSKM_FALSE && p_inEv->prm.resWakeup.isStepDone) {
503 p_svc->isStepDone = TSKM_TRUE;
504 isStateChg = TSKM_TRUE;
505 TSKM_PRINTF(TSKM_LOG_SVCSTATE, "%s:STEP DONE", p_svc->attr->name);
508 if (p_svc->waitResCnt > 0) {
510 if (p_svc->waitResCnt == 0) { // Transition when the wait runs out
511 if (p_inEv->prm.resWakeup.isLast) {
512 p_svc->state = TSKM_SVC_RUNNING; // Startup completed
513 TSKM_PRINTF(TSKM_LOG_SVCSTATE, "[ST:%d] RUN", p_svc->pid);
515 isStateChg = TSKM_TRUE;
521 /*********************************************************
522 * Response handler for the termination request
523 * ret:TRUE SVC state changed
524 * ret:FALSE SVC state not changed
525 *********************************************************/
526 TSKM_STATIC TSKM_BOOL_t resDownHandle(TSKM_SVC_CTX_t* p_svc,
527 const TSKM_EVENT_INFO_t* p_inEv) {
528 TSKM_ASSERT(p_svc->state == TSKM_SVC_DOWN);
529 TSKM_ASSERT(p_svc->waitResCnt > 0);
530 TSKM_BOOL_t isStateChg = TSKM_FALSE;
532 TSKM_PRINTF(TSKM_LOG_DEBUG, "pid:%d waitCnt:%d", p_svc->pid,
534 if (p_svc->waitResCnt > 0) {
536 if (p_svc->waitResCnt == 0) { // Transition when the wait runs out
537 if (p_inEv->prm.resWakeup.isLast) {
538 p_svc->state = TSKM_SVC_FINDOWN; // Termination complete
539 TSKM_PRINTF(TSKM_LOG_SVCSTATE, "[ST:%d] FIN_DOWN", p_svc->pid);
541 isStateChg = TSKM_TRUE;
547 /*********************************************************
548 * Response Handlers for DebugDump Requests
549 * ret:TRUE SVC state changed
550 * ret:FALSE SVC state not changed
551 *********************************************************/
552 TSKM_STATIC TSKM_BOOL_t resDebugDumpHandle(TSKM_SVC_CTX_t* p_svc,
553 const TSKM_EVENT_INFO_t* p_inEv) {
554 TSKM_BOOL_t isStateChg = TSKM_FALSE;
555 TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t *p_prm;
557 if (!p_inEv->hasExtend || !p_inEv->extendPrm) {
562 p_prm = (TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t *) p_inEv->extendPrm; // NOLINT (readability/casting)
564 // FALSE is specified here because the required service names have been added in the PrimaryLib.
565 tskm_sub_debugDumpRes(FALSE, p_prm->dumpMsg);
567 ERROR: return isStateChg;
570 /*********************************************************
571 * Service termination request
572 * ret:TRUE SVC state changed
573 * ret:FALSE SVC state not changed
574 *********************************************************/
575 TSKM_STATIC TSKM_BOOL_t reqExit(TSKM_SVC_CTX_t* p_svc,
576 const TSKM_EVENT_INFO_t* p_inEv) {
579 TSKM_ASSERT(p_svc->state == TSKM_SVC_RUNNING);
580 TSKM_ASSERT(p_svc->waitResCnt == 0);
581 TSKM_GSTEP_REQ_INFO_t req = { 0 };
583 req.svcId = p_svc->attr->svcId;
584 req.localStep = TSKM_LSTEP_ALL;
585 tskmRet = tskm_svcDownRequest(p_svc, &req);
590 // LCOV_EXCL_START 8: dead code
591 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
592 ERROR: ret = tskm_pf_terminateProcGroup(static_cast<uint16_t>(p_svc->pid));
593 if (ret != 0) { // LCOV_EXCL_BR_LINE 8: dead code
594 TSKM_PRINTF(TSKM_LOG_WARN, "ret = %d", ret);
601 /*********************************************************
602 * Service termination handler
603 * ret:TRUE SVC state changed
604 * ret:FALSE SVC state not changed
605 *********************************************************/
606 TSKM_STATIC TSKM_BOOL_t repTermHandle(TSKM_SVC_CTX_t* p_svc,
607 const TSKM_EVENT_INFO_t* p_inEv) {
611 if (p_svc->attr->lifeCycle == TSKM_SVC_LC_DYNAMIC) {
612 if (p_svc->state != TSKM_SVC_DOWN) {
613 // A STATE other than DOWN does not terminate.
614 TSKM_PRINTF(TSKM_LOG_ERROR, "ERR TERM %s(%d) waitCnt:%d",
615 p_svc->attr->name, p_svc->pid, p_svc->waitResCnt);
619 // The resident service terminated.
620 TSKM_PRINTF(TSKM_LOG_ERROR, "ERR TERM %s(%d) waitCnt:%d", p_svc->attr->name,
621 p_svc->pid, p_svc->waitResCnt);
625 TSKM_PRINTF(TSKM_LOG_STATE, "[ST:%d] DORMANT", p_svc->pid);
627 p_svc->state = TSKM_SVC_DORMANT;
628 p_svc->waitResCnt = 0;
631 if (p_svc->attr->type == TSKM_SVC_TYPE_NATIVE) {
632 EFrameworkunifiedStatus taskmanagerStatus;
633 TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx();
634 SS_String availabilityName = p_svc->attr->name;
635 availabilityName.append("/Availability");
637 taskmanagerStatus = FrameworkunifiedUnsubscribeNotificationWithCallback(
638 p_main->hApp, availabilityName.c_str());
639 if (eFrameworkunifiedStatusOK != taskmanagerStatus) {
643 p_svc->isAvailable = TSKM_FALSE;
646 HANDLE hMq = McOpenSender(FRAMEWORKUNIFIED_NS_NPSERVICE);
647 if (NULL == hMq) { // LCOV_EXCL_BR_LINE 4: NSFW error case.
648 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
649 TSKM_ASSERT(0); // LCOV_EXCL_LINE 4: NSFW error case.
651 ServiceAvailability availInfo = { };
653 snprintf(availInfo.cServiceName, MAX_NAME_SIZE_APP, "%s",
655 availInfo.eServiceAvailability = eFrameworkunifiedServiceNotAvailable;
657 taskmanagerStatus = NPPublishNotification(hMq, p_svc->attr->name,
658 availabilityName.c_str(), &availInfo,
660 if (eFrameworkunifiedStatusOK != taskmanagerStatus) {
664 taskmanagerStatus = McClose(hMq);
665 if (eFrameworkunifiedStatusOK != taskmanagerStatus) { // LCOV_EXCL_BR_LINE 4: NSFW error case.
666 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
667 TSKM_ASSERT(0); // LCOV_EXCL_LINE 4: NSFW error case.
672 if (p_inEv->errCode != TSKM_E_OK) {
674 // Notify 'NG' at Relaunch after abnormal termination
675 p_svc->bootInfo.resetStatus = e_SS_SM_RESET_STATUS_NG;
677 ret = svcErrTermPost(p_svc);
678 if (ret != TSKM_E_OK) {
682 // NONE is notified at Relaunch after normal completion.
683 p_svc->bootInfo.resetStatus = e_SS_SM_RESET_STATUS_NONE;
689 /*********************************************************
690 * Get service context
691 *********************************************************/
693 tskm_svcsGetSvcBySvcId(TSKM_SVCS_CTX_t* p_svcs, TSKM_SVCID_t svcId) {
694 return getSvcCtxBySvcId(p_svcs, svcId);
697 /*********************************************************
698 * Get service context
699 *********************************************************/
701 tskm_svcsGetSvcByPid(TSKM_SVCS_CTX_t* p_svcs, pid_t pid) {
702 return getSvcCtxByPid(p_svcs, pid);
705 /*********************************************************
706 * Check for waiting services
707 *********************************************************/
708 TSKM_BOOL_t tskm_svcsIsWaiting(TSKM_SVCS_CTX_t* p_svcs) {
710 for (ii = 0; ii < p_svcs->svcNum; ii++) {
711 if (p_svcs->svcList[ii].waitResCnt > 0
712 || p_svcs->svcList[ii].state == TSKM_SVC_WAITCONNECT) {
719 /*********************************************************
720 * Check if ShutdownWait services are terminated
721 *********************************************************/
722 TSKM_SVC_WAIT_STATE_t tskm_svcsGetSvcTermWaitState(TSKM_SVCS_CTX_t* p_svcs) {
724 TSKM_SVC_WAIT_STATE_t waitState = TSKM_SVC_WAIT_NONE;
726 for (ii = 0; ii < p_svcs->svcNum; ii++) {
727 if (p_svcs->svcList[ii].attr->shotdownWait) {
728 // Check shutdownWait SVC Only
729 if (p_svcs->svcList[ii].state != TSKM_SVC_DORMANT) {
730 // DORMANT is terminated or not started, so no checking is required
731 if (TSKM_SVC_LC_DYNAMIC != p_svcs->svcList[ii].attr->lifeCycle
732 && p_svcs->svcList[ii].state != TSKM_SVC_FINDOWN) { // Check of termination of resident SVCs
733 waitState = TSKM_SVC_WAIT_BOTH;
735 } else if (TSKM_SVC_LC_DYNAMIC == p_svcs->svcList[ii].attr->lifeCycle) { // Check of termination of non-resident SVCs
736 waitState = TSKM_SVC_WAIT_TRANSIENT;
744 /*********************************************************
745 * Update boot info of all services
746 *********************************************************/
747 TSKM_ERR_t tskm_svcsSetBootInfo(TSKM_SVCS_CTX_t* p_svcs,
748 T_SS_SM_START_DataStructType* p_info,
749 T_SS_SM_START_ExtDataStructType *p_exInfo) {
752 for (ii = 0; ii < p_svcs->svcNum; ii++) {
753 p_svcs->svcList[ii].bootInfo = *p_info;
754 p_svcs->svcList[ii].extBootInfo = *p_exInfo;
759 /*********************************************************
760 * Terminates a running non-resident services
761 *********************************************************/
762 TSKM_ERR_t tskm_svcsAvtiveSvcTerm(TSKM_SVCS_CTX_t* p_svcs) {
765 for (ii = 0; ii < p_svcs->svcNum; ii++) {
766 TSKM_SVC_CTX_t* p_svc = &p_svcs->svcList[ii];
768 if (TSKM_SVC_LC_DYNAMIC == p_svc->attr->lifeCycle && // Non-resident SVC
769 TSKM_SVC_RUNNING == p_svc->state && p_svc->waitResCnt == 0) { // Running
771 TSKM_GSTEP_REQ_INFO_t req = { 0 };
773 req.svcId = p_svc->attr->svcId;
774 req.localStep = TSKM_LSTEP_ALL;
775 tskmRet = tskm_svcDownRequest(p_svc, &req);
786 /*********************************************************
787 * Calls back the DebugDump of the running services
788 *********************************************************/
789 TSKM_ERR_t tskm_svcsCallDebugDump(TSKM_SVCS_CTX_t* p_svcs) {
790 for (uint32_t ii = 0; ii < p_svcs->svcNum; ii++) {
791 TSKM_SVC_CTX_t* p_svc = &p_svcs->svcList[ii];
793 if (TSKM_SVC_RUNNING == p_svc->state) { // Running
794 TSKM_EVENT_INFO_t ev;
795 bzero(&ev, sizeof(ev));
797 // Send DebugDump request
798 ev.event = TSKM_EV_PRI_REQ_DEBUGDUMP;
799 ev.errCode = TSKM_E_OK;
800 if (0 >= tskm_sockSend(p_svc->connFd, &ev)) {
808 ERROR: return TSKM_E_NG;
811 /*********************************************************
812 * Calls back the LowMemory of the running services
813 *********************************************************/
814 TSKM_ERR_t tskm_svcsCallLowMem(TSKM_SVCS_CTX_t* p_svcs) {
815 for (uint32_t ii = 0; ii < p_svcs->svcNum; ii++) {
816 TSKM_SVC_CTX_t* p_svc = &p_svcs->svcList[ii];
817 if (TSKM_SVC_RUNNING == p_svc->state) { // Running
818 TSKM_EVENT_INFO_t ev;
819 bzero(&ev, sizeof(ev));
821 // Send LowMemory detection notification
822 ev.event = TSKM_EV_PRI_REP_LOWMEM;
823 ev.errCode = TSKM_E_OK;
824 if (0 >= tskm_sockSend(p_svc->connFd, &ev)) {
832 ERROR: return TSKM_E_NG;
835 /*********************************************************
837 *********************************************************/
838 TSKM_ERR_t tskm_svcEventHandle(TSKM_SVC_CTX_t* p_svc, TSKM_EVENT_INFO_t* p_ev) {
840 TSKM_BOOL_t isStateChg = TSKM_FALSE;
842 if (isSvcEvent(p_ev) == TSKM_FALSE) {
843 // If it is not an event for the service, it will be sent as follows.
848 switch (p_ev->event) {
849 case TSKM_EV_PRI_REP_CONNECT: // Connection Registration from Service
850 isStateChg = connectHandle(p_svc, p_ev);
852 case TSKM_EV_PRI_REP_DISCONNECT: // Disconnection Registration from Service
853 isStateChg = disConnectHandle(p_svc, p_ev);
855 case TSKM_EV_PRI_RES_WAKEUP: // Response to a startup request from a service
856 isStateChg = resWakeupHandle(p_svc, p_ev);
858 case TSKM_EV_PRI_RES_DOWN:
859 isStateChg = resDownHandle(p_svc, p_ev);
861 case TSKM_EV_PRI_RES_DEBUGDUMP:
862 isStateChg = resDebugDumpHandle(p_svc, p_ev);
864 case TSKM_EV_PRI_REQ_EXIT:
865 isStateChg = reqExit(p_svc, p_ev);
867 case TSKM_EV_SVC_REP_TERM: // Service termination
868 isStateChg = repTermHandle(p_svc, p_ev);
874 // Overwrite service state change
876 p_ev->event = TSKM_EV_LCL_CHG_SVC_STATE;
877 p_ev->prm.chgSvc.svcId = p_svc->attr->svcId;
879 p_ev->event = TSKM_EV_NOP;
885 /*********************************************************
887 *********************************************************/
888 TSKM_ERR_t tskm_svcExec(TSKM_SVC_CTX_t* p_svc) {
889 return svcExec(p_svc);
892 /*********************************************************
893 * Issue a startup request to the service
894 *********************************************************/
895 TSKM_ERR_t tskm_svcWakeupRequest(TSKM_SVC_CTX_t* p_svc,
896 TSKM_GSTEP_REQ_INFO_t* p_req) {
897 return svcWakeupRequest(p_svc, p_req);
900 /*********************************************************
901 * Issue a termination request to the service
902 *********************************************************/
903 TSKM_ERR_t tskm_svcDownRequest(TSKM_SVC_CTX_t* p_svc,
904 TSKM_GSTEP_REQ_INFO_t* p_req) {
906 TSKM_EVENT_INFO_t ev;
908 bzero(&ev, sizeof(ev));
910 if (tskm_svcIsCommunicatable(p_svc) == TSKM_FALSE) {
914 ev.event = TSKM_EV_PRI_REQ_DOWN;
915 ev.errCode = TSKM_E_OK;
916 ev.prm.reqDown.localStep = p_req->localStep;
918 ret = tskm_sockSend(p_svc->connFd, &ev);
924 p_svc->state = TSKM_SVC_DOWN;
927 ERROR: return TSKM_E_NG;
930 /*********************************************************
931 * Prohibit starting service
932 *********************************************************/
933 TSKM_ERR_t tskm_svcDisableRequest(TSKM_SVC_CTX_t* p_svc) {
934 if (p_svc->state == TSKM_SVC_DORMANT || p_svc->state == TSKM_SVC_DISABLE) {
935 p_svc->state = TSKM_SVC_DISABLE;
941 /*********************************************************
942 * Allow starting service
943 *********************************************************/
944 TSKM_ERR_t tskm_svcEnableRequest(TSKM_SVC_CTX_t* p_svc) {
945 if (p_svc->state == TSKM_SVC_DISABLE) {
946 p_svc->state = TSKM_SVC_DORMANT;
951 /*********************************************************
952 * Queriy whether the service is ready for communication
953 *********************************************************/
954 TSKM_BOOL_t tskm_svcIsCommunicatable(TSKM_SVC_CTX_t* p_svc) {
955 TSKM_BOOL_t ret = TSKM_FALSE;
956 if (p_svc == NULL || p_svc->attr->type == TSKM_SVC_TYPE_UNKNONW) {
958 switch (p_svc->state) {
959 case TSKM_SVC_WAKEUP:
960 case TSKM_SVC_RUNNING:
969 } // LCOV_EXCL_BR_LINE 10: Final line