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