Fix static analysis issue
[platform/core/appfw/rpc-port.git] / utils / src / logger.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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 <stdio.h>
18 #include <stdlib.h>
19
20 #include "log-private.hh"
21 #include "logger.hh"
22
23 namespace rpc_port {
24 namespace util {
25
26 Logger::Logger(int pid, int fd, IEvent* listener)
27   : pid_(pid), fd_(fd), listener_(listener) {
28   thread_ = std::thread([&]() {
29       GMainContext* context = g_main_context_new();
30       GIOChannel* io = g_io_channel_unix_new(fd_);
31       GIOCondition cond = static_cast<GIOCondition>(
32           G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR | G_IO_NVAL);
33       GSource* source = g_io_create_watch(io, cond);
34       g_source_set_callback(source, (GSourceFunc)OnDataReceivedCb, this,
35           nullptr);
36       g_source_set_priority(source, G_PRIORITY_DEFAULT);
37       g_source_attach(source, context);
38       g_source_unref(source);
39
40       loop_ = g_main_loop_new(context, FALSE);
41       g_main_context_push_thread_default(context);
42
43       g_main_loop_run(loop_);
44
45       if (!g_source_is_destroyed(source))
46         g_source_destroy(source);
47
48       g_io_channel_unref(io);
49
50       g_main_context_pop_thread_default(context);
51       g_main_loop_unref(loop_);
52       g_main_context_unref(context);
53     });
54 }
55
56 Logger::~Logger() {
57   if (g_main_loop_is_running(loop_))
58     g_main_loop_quit(loop_);
59
60   thread_.join();
61
62   if (fd_ > 0)
63     close(fd_);
64 }
65
66 int Logger::GetPid() {
67   return pid_;
68 }
69
70 int Logger::GetFd() {
71   return fd_;
72 }
73
74 int Logger::Read(void* buf, unsigned int size) {
75   char* buffer = static_cast<char*>(buf);
76   unsigned int left = size;
77   while (left) {
78     ssize_t read_size = read(fd_, buffer, left);
79     if (read_size <= 0) {
80       _E("Failed to read data. fd(%d), errno(%d)", fd_, errno);
81       return -1;
82     }
83
84     left -= read_size;
85     buffer += read_size;
86   }
87   return 0;
88 }
89
90 rpc_port_parcel_h Logger::Read()
91 {
92   int size = 0;
93   int ret = Read(reinterpret_cast<void*>(&size), sizeof(size));
94   if (ret < 0 || size <= 0)
95     return nullptr;
96
97   auto* buf = new unsigned char[size];
98   ret = Read(static_cast<void*>(buf), size);
99   if (ret < 0) {
100     delete[] buf;
101     return nullptr;
102   }
103
104   rpc_port_parcel_h parcel = nullptr;
105   rpc_port_parcel_create(&parcel);
106   rpc_port_parcel_burst_write(parcel, buf, size);
107   delete[] buf;
108   return parcel;
109 }
110
111 gboolean Logger::OnDataReceivedCb(GIOChannel* io,
112     GIOCondition cond, gpointer data) {
113   auto* logger = static_cast<Logger*>(data);
114   auto* listener = logger->listener_;
115   int fd = g_io_channel_unix_get_fd(io);
116   int pid = logger->pid_;
117
118   if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
119     _E("Error(%d), fd(%d)", cond, fd);
120     listener->OnDisconnected(pid, fd);
121     return G_SOURCE_REMOVE;
122   }
123
124   rpc_port_parcel_h parcel = logger->Read();
125   listener->OnDataReceived(pid, parcel);
126   rpc_port_parcel_destroy(parcel);
127   return G_SOURCE_CONTINUE;
128 }
129
130 }  // namespace util
131 }  // namespace rpc_port