1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <fcntl.h>
17 #include <stdio.h>
18 #include "appspawn_kickdog.h"
19 
OpenAndWriteToProc(const char * procName,const char * writeStr,size_t writeLen)20 static int OpenAndWriteToProc(const char *procName, const char *writeStr, size_t writeLen)
21 {
22     if (writeStr == NULL) {
23         APPSPAWN_LOGE("Write string is null");
24         return -1;
25     }
26 
27     int procFd = open(procName, O_RDWR | O_CLOEXEC);
28     if (procFd == -1) {
29         APPSPAWN_LOGE("open %{public}s fail,errno:%{public}d", procName, errno);
30         return procFd;
31     }
32 
33     int writeResult = write(procFd, writeStr, writeLen);
34     if (writeResult != (int)writeLen) {
35         APPSPAWN_LOGE("write %{public}s fail,result:%{public}d", writeStr, writeResult);
36     } else {
37         APPSPAWN_LOGV("write %{public}s success", writeStr);
38     }
39 
40     close(procFd);
41     return writeResult;
42 }
43 
44 // Enable watchdog monitoring
OpenAppSpawnWatchdogFile(AppSpawnContent * content)45 static int OpenAppSpawnWatchdogFile(AppSpawnContent *content)
46 {
47     APPSPAWN_LOGI("OpenAppSpawnWatchdogFile");
48     int result = 0;
49     if (access(LINUX_APPSPAWN_WATCHDOG_FILE, F_OK) == 0) {
50         result = OpenAndWriteToProc(LINUX_APPSPAWN_WATCHDOG_FILE, LINUX_APPSPAWN_WATCHDOG_ON,
51             strlen(LINUX_APPSPAWN_WATCHDOG_ON));
52     } else {
53         result = OpenAndWriteToProc(HM_APPSPAWN_WATCHDOG_FILE, HM_APPSPAWN_WATCHDOG_ON,
54             strlen(HM_APPSPAWN_WATCHDOG_ON));
55     }
56     content->wdgOpened = (result != -1);
57     APPSPAWN_LOGI("open finish,result:%{public}d", result);
58     return result;
59 }
60 
KickAppSpawnWatchdog(void)61 static void KickAppSpawnWatchdog(void)
62 {
63     APPSPAWN_LOGI("kick proc begin");
64     int result = 0;
65     if (access(LINUX_APPSPAWN_WATCHDOG_FILE, F_OK) == 0) {
66         result = OpenAndWriteToProc(LINUX_APPSPAWN_WATCHDOG_FILE, LINUX_APPSPAWN_WATCHDOG_KICK,
67             strlen(LINUX_APPSPAWN_WATCHDOG_KICK));
68     } else {
69         result = OpenAndWriteToProc(HM_APPSPAWN_WATCHDOG_FILE, HM_APPSPAWN_WATCHDOG_KICK,
70             strlen(HM_APPSPAWN_WATCHDOG_KICK));
71     }
72     APPSPAWN_LOGI("kick end,result:%{public}d", result);
73 }
74 
ProcessTimerHandle(const TimerHandle taskHandle,void * context)75 static void ProcessTimerHandle(const TimerHandle taskHandle, void *context)
76 {
77     AppSpawnContent *wdgContent = (AppSpawnContent *)context;
78 
79     APPSPAWN_LOGI("kick appspawn dog start");
80 
81     if (!wdgContent->wdgOpened) {  //first time deal kernel file
82         OpenAppSpawnWatchdogFile(wdgContent);
83         return;
84     }
85 
86     KickAppSpawnWatchdog();
87 }
88 
CreateTimerLoopTask(AppSpawnContent * content)89 static void CreateTimerLoopTask(AppSpawnContent *content)
90 {
91     LoopHandle loop = LE_GetDefaultLoop();
92     TimerHandle timer = NULL;
93     int ret = LE_CreateTimer(loop, &timer, ProcessTimerHandle, (void *)content);
94     APPSPAWN_CHECK(ret == 0, return, "Failed to create timerLoopTask ret %{public}d", ret);
95     // start a timer to write kernel file every 10s
96     ret = LE_StartTimer(loop, timer, APPSPAWN_WATCHDOG_KICKTIME, INT64_MAX);
97     APPSPAWN_CHECK(ret == 0, return, "Failed to start timerLoopTask ret %{public}d", ret);
98 }
99 
AppSpawnKickDogStart(AppSpawnContent * content)100 void AppSpawnKickDogStart(AppSpawnContent *content)
101 {
102     if (content == NULL) {
103         APPSPAWN_LOGE("Content is null");
104         return;
105     }
106     CreateTimerLoopTask(content);
107     OpenAppSpawnWatchdogFile(content);
108 }