1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
5d9f0492fSopenharmony_ci * You may obtain a copy of the License at
6d9f0492fSopenharmony_ci *
7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8d9f0492fSopenharmony_ci *
9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
13d9f0492fSopenharmony_ci * limitations under the License.
14d9f0492fSopenharmony_ci */
15d9f0492fSopenharmony_ci
16d9f0492fSopenharmony_ci#include "le_signal.h"
17d9f0492fSopenharmony_ci
18d9f0492fSopenharmony_ci#include <signal.h>
19d9f0492fSopenharmony_ci#include <stdio.h>
20d9f0492fSopenharmony_ci#include <sys/signalfd.h>
21d9f0492fSopenharmony_ci#include <sys/socket.h>
22d9f0492fSopenharmony_ci#include <unistd.h>
23d9f0492fSopenharmony_ci
24d9f0492fSopenharmony_ci#include "le_loop.h"
25d9f0492fSopenharmony_ci#include "le_task.h"
26d9f0492fSopenharmony_ci#include "loop_event.h"
27d9f0492fSopenharmony_ci
28d9f0492fSopenharmony_cistatic LE_STATUS HandleSignalEvent_(const LoopHandle loop, const TaskHandle task, uint32_t oper)
29d9f0492fSopenharmony_ci{
30d9f0492fSopenharmony_ci    if (!LE_TEST_FLAGS(oper, EVENT_READ)) {
31d9f0492fSopenharmony_ci        return LE_FAILURE;
32d9f0492fSopenharmony_ci    }
33d9f0492fSopenharmony_ci    struct signalfd_siginfo fdsi;
34d9f0492fSopenharmony_ci    ssize_t s = read(GetSocketFd(task), &fdsi, sizeof(fdsi));
35d9f0492fSopenharmony_ci    LE_CHECK(s == sizeof(fdsi), return LE_FAILURE, "Failed to read sign %d %d", s, errno);
36d9f0492fSopenharmony_ci    SignalTask *sigTask = (SignalTask *)task;
37d9f0492fSopenharmony_ci    if (sigTask->processSignal) {
38d9f0492fSopenharmony_ci        sigTask->processSignal(&fdsi);
39d9f0492fSopenharmony_ci    }
40d9f0492fSopenharmony_ci    return LE_SUCCESS;
41d9f0492fSopenharmony_ci}
42d9f0492fSopenharmony_ci
43d9f0492fSopenharmony_cistatic void HandleSignalTaskClose_(const LoopHandle loopHandle, const TaskHandle signalHandle)
44d9f0492fSopenharmony_ci{
45d9f0492fSopenharmony_ci    BaseTask *task = (BaseTask *)signalHandle;
46d9f0492fSopenharmony_ci    DelTask((EventLoop *)loopHandle, task);
47d9f0492fSopenharmony_ci    CloseTask(loopHandle, task);
48d9f0492fSopenharmony_ci    close(task->taskId.fd);
49d9f0492fSopenharmony_ci}
50d9f0492fSopenharmony_ci
51d9f0492fSopenharmony_cistatic void PrintSigset(sigset_t mask)
52d9f0492fSopenharmony_ci{
53d9f0492fSopenharmony_ci    int cnt = 0;
54d9f0492fSopenharmony_ci    for (int sig = 1; sig < NSIG; sig++) {
55d9f0492fSopenharmony_ci        if (sigismember(&mask, sig)) {
56d9f0492fSopenharmony_ci            cnt++;
57d9f0492fSopenharmony_ci            printf("\t    %d(%s)\n", sig, strsignal(sig));
58d9f0492fSopenharmony_ci        }
59d9f0492fSopenharmony_ci    }
60d9f0492fSopenharmony_ci    if (cnt == 0) {
61d9f0492fSopenharmony_ci        printf("empty signal set\n");
62d9f0492fSopenharmony_ci    }
63d9f0492fSopenharmony_ci}
64d9f0492fSopenharmony_ci
65d9f0492fSopenharmony_cistatic void DumpSignalTaskInfo_(const TaskHandle task)
66d9f0492fSopenharmony_ci{
67d9f0492fSopenharmony_ci    INIT_CHECK(task != NULL, return);
68d9f0492fSopenharmony_ci    BaseTask *baseTask = (BaseTask *)task;
69d9f0492fSopenharmony_ci    SignalTask *signalTask = (SignalTask *)baseTask;
70d9f0492fSopenharmony_ci    printf("\tfd: %d \n", signalTask->base.taskId.fd);
71d9f0492fSopenharmony_ci    printf("\t  TaskType: %s \n", "SignalTask");
72d9f0492fSopenharmony_ci    printf("\t  sigNumber: %d \n", signalTask->sigNumber);
73d9f0492fSopenharmony_ci    printf("\t  signal: \n");
74d9f0492fSopenharmony_ci    PrintSigset(signalTask->mask);
75d9f0492fSopenharmony_ci}
76d9f0492fSopenharmony_ci
77d9f0492fSopenharmony_ciLE_STATUS LE_CreateSignalTask(const LoopHandle loopHandle, SignalHandle *signalHandle, LE_ProcessSignal processSignal)
78d9f0492fSopenharmony_ci{
79d9f0492fSopenharmony_ci    LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters");
80d9f0492fSopenharmony_ci    LE_CHECK(processSignal != NULL, return LE_FAILURE, "Invalid parameters processSignal");
81d9f0492fSopenharmony_ci    sigset_t mask;
82d9f0492fSopenharmony_ci    sigemptyset(&mask);
83d9f0492fSopenharmony_ci    int sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
84d9f0492fSopenharmony_ci    LE_CHECK(sfd > 0, return -1, "Failed to create signal fd");
85d9f0492fSopenharmony_ci    LE_BaseInfo info = {TASK_SIGNAL, NULL};
86d9f0492fSopenharmony_ci    SignalTask *task = (SignalTask *)CreateTask(loopHandle, sfd, &info, sizeof(SignalTask));
87d9f0492fSopenharmony_ci    LE_CHECK(task != NULL, return LE_NO_MEMORY, "Failed to create task");
88d9f0492fSopenharmony_ci    task->base.handleEvent = HandleSignalEvent_;
89d9f0492fSopenharmony_ci    task->base.innerClose = HandleSignalTaskClose_;
90d9f0492fSopenharmony_ci    task->base.dumpTaskInfo = DumpSignalTaskInfo_;
91d9f0492fSopenharmony_ci    task->sigNumber = 0;
92d9f0492fSopenharmony_ci    sigemptyset(&task->mask);
93d9f0492fSopenharmony_ci    task->processSignal = processSignal;
94d9f0492fSopenharmony_ci    *signalHandle = (SignalHandle)task;
95d9f0492fSopenharmony_ci    return LE_SUCCESS;
96d9f0492fSopenharmony_ci}
97d9f0492fSopenharmony_ci
98d9f0492fSopenharmony_ciLE_STATUS LE_AddSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal)
99d9f0492fSopenharmony_ci{
100d9f0492fSopenharmony_ci    LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters");
101d9f0492fSopenharmony_ci    EventLoop *loop = (EventLoop *)loopHandle;
102d9f0492fSopenharmony_ci    SignalTask *task = (SignalTask *)signalHandle;
103d9f0492fSopenharmony_ci    LE_LOGI("LE_AddSignal %d %d", signal, task->sigNumber);
104d9f0492fSopenharmony_ci    if (sigismember(&task->mask, signal)) {
105d9f0492fSopenharmony_ci        return LE_SUCCESS;
106d9f0492fSopenharmony_ci    }
107d9f0492fSopenharmony_ci    sigaddset(&task->mask, signal);
108d9f0492fSopenharmony_ci    sigprocmask(SIG_BLOCK, &task->mask, NULL);
109d9f0492fSopenharmony_ci    int sfd = signalfd(GetSocketFd(signalHandle), &task->mask, SFD_NONBLOCK | SFD_CLOEXEC);
110d9f0492fSopenharmony_ci    LE_CHECK(sfd > 0, return -1, "Failed to create signal fd");
111d9f0492fSopenharmony_ci    if (task->sigNumber == 0) {
112d9f0492fSopenharmony_ci        loop->addEvent(loop, (const BaseTask *)task, EVENT_READ);
113d9f0492fSopenharmony_ci    } else {
114d9f0492fSopenharmony_ci        loop->modEvent(loop, (const BaseTask *)task, EVENT_READ);
115d9f0492fSopenharmony_ci    }
116d9f0492fSopenharmony_ci    task->sigNumber++;
117d9f0492fSopenharmony_ci    return LE_SUCCESS;
118d9f0492fSopenharmony_ci}
119d9f0492fSopenharmony_ci
120d9f0492fSopenharmony_ciLE_STATUS LE_RemoveSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal)
121d9f0492fSopenharmony_ci{
122d9f0492fSopenharmony_ci    LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters");
123d9f0492fSopenharmony_ci    EventLoop *loop = (EventLoop *)loopHandle;
124d9f0492fSopenharmony_ci    SignalTask *task = (SignalTask *)signalHandle;
125d9f0492fSopenharmony_ci    LE_LOGI("LE_RemoveSignal %d %d", signal, task->sigNumber);
126d9f0492fSopenharmony_ci    if (!sigismember(&task->mask, signal)) {
127d9f0492fSopenharmony_ci        return LE_SUCCESS;
128d9f0492fSopenharmony_ci    }
129d9f0492fSopenharmony_ci    sigdelset(&task->mask, signal);
130d9f0492fSopenharmony_ci    task->sigNumber--;
131d9f0492fSopenharmony_ci    int sfd = signalfd(GetSocketFd(signalHandle), &task->mask, SFD_NONBLOCK | SFD_CLOEXEC);
132d9f0492fSopenharmony_ci    LE_CHECK(sfd > 0, return -1, "Failed to create signal fd");
133d9f0492fSopenharmony_ci    if (task->sigNumber <= 0) {
134d9f0492fSopenharmony_ci        loop->delEvent(loop, GetSocketFd(signalHandle), EVENT_READ);
135d9f0492fSopenharmony_ci    }
136d9f0492fSopenharmony_ci    return LE_SUCCESS;
137d9f0492fSopenharmony_ci}
138d9f0492fSopenharmony_ci
139d9f0492fSopenharmony_civoid LE_CloseSignalTask(const LoopHandle loopHandle, const SignalHandle signalHandle)
140d9f0492fSopenharmony_ci{
141d9f0492fSopenharmony_ci    LE_CHECK(loopHandle != NULL && signalHandle != NULL, return, "Invalid parameters");
142d9f0492fSopenharmony_ci    LE_CloseTask(loopHandle, signalHandle);
143d9f0492fSopenharmony_ci}
144