xref: /base/hiviewdfx/hilog/services/hilogd/main.cpp (revision 2498b56b)
1/*
2 * Copyright (c) 2021 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 <iostream>
17#include <sys/stat.h>
18#include <sys/prctl.h>
19#include <sys/stat.h>
20#include <future>
21#include <unistd.h>
22#include <csignal>
23#include <fcntl.h>
24#include <hilog_input_socket_server.h>
25#include <properties.h>
26#include <log_utils.h>
27
28#include "cmd_executor.h"
29#include "ffrt.h"
30#include "flow_control.h"
31#include "log_kmsg.h"
32#include "log_collector.h"
33#include "service_controller.h"
34
35#ifdef DEBUG
36#include <cstdio>
37#include <cerrno>
38#endif
39
40namespace OHOS {
41namespace HiviewDFX {
42using namespace std;
43
44static const string SYSTEM_BG_STUNE = "/dev/stune/system-background/cgroup.procs";
45static const string SYSTEM_BG_CPUSET = "/dev/cpuset/system-background/cgroup.procs";
46static const string SYSTEM_BG_BLKIO  = "/dev/blkio/system-background/cgroup.procs";
47
48#ifdef DEBUG
49static int g_fd = -1;
50#endif
51
52static void SigHandler(int sig)
53{
54    if (sig == SIGINT) {
55#ifdef DEBUG
56        if (g_fd > 0) {
57            close(g_fd);
58            g_fd = -1;
59        }
60#endif
61    }
62}
63
64static bool WriteStringToFile(int fd, const std::string& content)
65{
66    const char *p = content.data();
67    size_t remaining = content.size();
68    while (remaining > 0) {
69        ssize_t n = write(fd, p, remaining);
70        if (n == -1) {
71            return false;
72        }
73        p += n;
74        remaining -= static_cast<size_t>(n);
75    }
76    return true;
77}
78
79static bool WriteStringToFile(const std::string& content, const std::string& filePath)
80{
81    int ret = WaitingToDo(WAITING_DATA_MS, filePath, [](const string &path) {
82        int fd;
83        if (!access(path.c_str(), W_OK)) {
84            fd = open(path.c_str(), O_WRONLY | O_CLOEXEC);
85            if (fd >= 0) {
86                close(fd);
87                return RET_SUCCESS;
88            }
89        }
90        return RET_FAIL;
91    });
92    if (ret != RET_SUCCESS) {
93        return false;
94    }
95    if (access(filePath.c_str(), W_OK)) {
96        return false;
97    }
98    int fd = open(filePath.c_str(), O_WRONLY | O_CLOEXEC);
99    if (fd < 0) {
100        return false;
101    }
102    bool result = WriteStringToFile(fd, content);
103    close(fd);
104    return result;
105}
106
107#ifdef DEBUG
108static void RedirectStdStreamToLogFile()
109{
110    int ret = WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, [](const string &path) {
111        struct stat s;
112        if (stat(path.c_str(), &s) != -1) {
113            return RET_SUCCESS;
114        }
115        return RET_FAIL;
116    });
117    if (ret == RET_SUCCESS) {
118        const char *path = HILOG_FILE_DIR"hilogd_debug.txt";
119        int mask = O_WRONLY | O_APPEND | O_CREAT;
120        struct stat st;
121        if (stat(path, &st) == -1) {
122            mask |= O_CREAT;
123        }
124        int fd = open(path, mask, S_IWUSR | S_IWGRP);
125        if (fd > 0) {
126            g_fd = dup2(fd, fileno(stdout));
127        } else {
128            std::cout << "open file error: ";
129            PrintErrorno(errno);
130        }
131    }
132}
133#endif
134
135int HilogdEntry()
136{
137    const int hilogFileMask = 0022;
138    umask(hilogFileMask);
139
140#ifdef DEBUG
141    RedirectStdStreamToLogFile();
142#endif
143    std::signal(SIGINT, SigHandler);
144    HilogBuffer hilogBuffer(true);
145    LogCollector logCollector(hilogBuffer);
146
147    // Start log_collector
148#ifndef __RECV_MSG_WITH_UCRED_
149    auto onDataReceive = [&logCollector](std::vector<char>& data, int dataLen) {
150        logCollector.onDataRecv(data, dataLen);
151    };
152#else
153    auto onDataReceive = [&logCollector](const ucred& cred, std::vector<char>& data, int dataLen) {
154        logCollector.onDataRecv(cred, data, dataLen);
155    };
156#endif
157
158    HilogInputSocketServer incomingLogsServer(onDataReceive);
159    if (incomingLogsServer.Init() < 0) {
160#ifdef DEBUG
161        cout << "Failed to init input server socket ! ";
162        PrintErrorno(errno);
163#endif
164    } else {
165#ifdef DEBUG
166        cout << "Begin to listen !\n";
167#endif
168        incomingLogsServer.RunServingThread();
169    }
170
171    HilogBuffer kmsgBuffer(false);
172    ffrt::submit([&hilogBuffer, &kmsgBuffer]() {
173        int ret = WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, [](const string &path) {
174            struct stat s;
175            if (stat(path.c_str(), &s) != -1) {
176                return RET_SUCCESS;
177            }
178            return RET_FAIL;
179        });
180        if (ret == RET_SUCCESS) {
181            RestorePersistJobs(hilogBuffer, kmsgBuffer);
182        }
183    }, {}, {}, ffrt::task_attr().name("hilogd.pst_res"));
184
185    bool kmsgEnable = IsKmsgSwitchOn();
186    if (kmsgEnable) {
187        LogKmsg& logKmsg = LogKmsg::GetInstance(kmsgBuffer);
188        logKmsg.Start();
189    }
190
191    ffrt::submit([]() {
192        string myPid = to_string(getprocpid());
193        (void)WriteStringToFile(myPid, SYSTEM_BG_STUNE);
194        (void)WriteStringToFile(myPid, SYSTEM_BG_CPUSET);
195        (void)WriteStringToFile(myPid, SYSTEM_BG_BLKIO);
196    }, {}, {}, ffrt::task_attr().name("hilogd.cgroup_set"));
197
198    std::thread([&logCollector, &hilogBuffer, &kmsgBuffer] () {
199        prctl(PR_SET_NAME, "hilogd.cmd");
200        CmdList controlCmdList {
201            IoctlCmd::PERSIST_START_RQST,
202            IoctlCmd::PERSIST_STOP_RQST,
203            IoctlCmd::PERSIST_QUERY_RQST,
204            IoctlCmd::PERSIST_REFRESH_RQST,
205            IoctlCmd::PERSIST_CLEAR_RQST,
206            IoctlCmd::BUFFERSIZE_GET_RQST,
207            IoctlCmd::BUFFERSIZE_SET_RQST,
208            IoctlCmd::STATS_QUERY_RQST,
209            IoctlCmd::STATS_CLEAR_RQST,
210            IoctlCmd::DOMAIN_FLOWCTRL_RQST,
211            IoctlCmd::LOG_REMOVE_RQST,
212            IoctlCmd::KMSG_ENABLE_RQST,
213        };
214        CmdExecutor controlExecutor(logCollector, hilogBuffer, kmsgBuffer, controlCmdList, ("hilogd.control"));
215        controlExecutor.MainLoop(CONTROL_SOCKET_NAME);
216    }).detach();
217
218    CmdList outputList {IoctlCmd::OUTPUT_RQST};
219    CmdExecutor outputExecutor(logCollector, hilogBuffer, kmsgBuffer, outputList, ("hilogd.output"));
220    outputExecutor.MainLoop(OUTPUT_SOCKET_NAME);
221
222    return 0;
223}
224} // namespace HiviewDFX
225} // namespace OHOS
226
227int main()
228{
229    (void)OHOS::HiviewDFX::HilogdEntry();
230    return 0;
231}
232