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 "le_signal.h"
17
18 #include <signal.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <sys/signalfd.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include "le_loop.h"
26 #include "le_task.h"
27 #include "loop_event.h"
28
HandleSignalEvent_(const LoopHandle loop,const TaskHandle task,uint32_t oper)29 static LE_STATUS HandleSignalEvent_(const LoopHandle loop, const TaskHandle task, uint32_t oper)
30 {
31 if (!LE_TEST_FLAGS(oper, Event_Read)) {
32 return LE_FAILURE;
33 }
34 struct signalfd_siginfo fdsi;
35 ssize_t s = read(GetSocketFd(task), &fdsi, sizeof(fdsi));
36 LE_CHECK(s == sizeof(fdsi), return LE_FAILURE, "Failed to read sign");
37 SignalTask *sigTask = (SignalTask *)task;
38 if (sigTask->processSignal) {
39 sigTask->processSignal(&fdsi);
40 }
41 return LE_SUCCESS;
42 }
43
HandleSignalTaskClose_(const LoopHandle loopHandle,const TaskHandle signalHandle)44 static void HandleSignalTaskClose_(const LoopHandle loopHandle, const TaskHandle signalHandle)
45 {
46 BaseTask *task = (BaseTask *)signalHandle;
47 CloseTask(loopHandle, task);
48 close(task->taskId.fd);
49 }
50
LE_CreateSignalTask(const LoopHandle loopHandle,SignalHandle * signalHandle,LE_ProcessSignal processSignal)51 LE_STATUS LE_CreateSignalTask(const LoopHandle loopHandle, SignalHandle *signalHandle, LE_ProcessSignal processSignal)
52 {
53 LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters");
54 LE_CHECK(processSignal != NULL, return LE_FAILURE, "Invalid parameters processSignal");
55 sigset_t mask;
56 sigemptyset(&mask);
57 int sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
58 LE_CHECK(sfd > 0, return -1, "Failed to create signal fd");
59 LE_BaseInfo info = {TASK_SIGNAL, NULL};
60 SignalTask *task = (SignalTask *)CreateTask(loopHandle, sfd, &info, sizeof(SignalTask));
61 LE_CHECK(task != NULL, return LE_NO_MEMORY, "Failed to create task");
62 task->base.handleEvent = HandleSignalEvent_;
63 task->base.innerClose = HandleSignalTaskClose_;
64 task->sigNumber = 0;
65 sigemptyset(&task->mask);
66 task->processSignal = processSignal;
67 *signalHandle = (SignalHandle)task;
68 return LE_SUCCESS;
69 }
70
LE_AddSignal(const LoopHandle loopHandle,const SignalHandle signalHandle,int signal)71 LE_STATUS LE_AddSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal)
72 {
73 LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters");
74 EventLoop *loop = (EventLoop *)loopHandle;
75 SignalTask *task = (SignalTask *)signalHandle;
76 LE_LOGI("LE_AddSignal %d %d", signal, task->sigNumber);
77 if (sigismember(&task->mask, signal)) {
78 return LE_SUCCESS;
79 }
80 sigaddset(&task->mask, signal);
81 sigprocmask(SIG_BLOCK, &task->mask, NULL);
82 int sfd = signalfd(GetSocketFd(signalHandle), &task->mask, SFD_NONBLOCK | SFD_CLOEXEC);
83 LE_CHECK(sfd > 0, return -1, "Failed to create signal fd");
84 if (task->sigNumber == 0) {
85 loop->addEvent(loop, (const BaseTask *)task, Event_Read);
86 } else {
87 loop->modEvent(loop, (const BaseTask *)task, Event_Read);
88 }
89 task->sigNumber++;
90 return LE_SUCCESS;
91 }
92
LE_RemoveSignal(const LoopHandle loopHandle,const SignalHandle signalHandle,int signal)93 LE_STATUS LE_RemoveSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal)
94 {
95 LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters");
96 EventLoop *loop = (EventLoop *)loopHandle;
97 SignalTask *task = (SignalTask *)signalHandle;
98 LE_LOGI("LE_RemoveSignal %d %d", signal, task->sigNumber);
99 if (!sigismember(&task->mask, signal)) {
100 return LE_SUCCESS;
101 }
102 sigdelset(&task->mask, signal);
103 task->sigNumber--;
104 int sfd = signalfd(GetSocketFd(signalHandle), &task->mask, SFD_NONBLOCK | SFD_CLOEXEC);
105 LE_CHECK(sfd > 0, return -1, "Failed to create signal fd");
106 if (task->sigNumber <= 0) {
107 loop->delEvent(loop, GetSocketFd(signalHandle), Event_Read);
108 }
109 return LE_SUCCESS;
110 }
111
LE_CloseSignalTask(const LoopHandle loopHandle,const SignalHandle signalHandle)112 void LE_CloseSignalTask(const LoopHandle loopHandle, const SignalHandle signalHandle)
113 {
114 LE_CHECK(loopHandle != NULL && signalHandle != NULL, return, "Invalid parameters");
115 LE_CloseTask(loopHandle, signalHandle);
116 }
117