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 <sys/signalfd.h> 21#include <sys/socket.h> 22#include <unistd.h> 23 24#include "le_loop.h" 25#include "le_task.h" 26#include "loop_event.h" 27 28static LE_STATUS HandleSignalEvent_(const LoopHandle loop, const TaskHandle task, uint32_t oper) 29{ 30 if (!LE_TEST_FLAGS(oper, EVENT_READ)) { 31 return LE_FAILURE; 32 } 33 struct signalfd_siginfo fdsi; 34 ssize_t s = read(GetSocketFd(task), &fdsi, sizeof(fdsi)); 35 LE_CHECK(s == sizeof(fdsi), return LE_FAILURE, "Failed to read sign %d %d", s, errno); 36 SignalTask *sigTask = (SignalTask *)task; 37 if (sigTask->processSignal) { 38 sigTask->processSignal(&fdsi); 39 } 40 return LE_SUCCESS; 41} 42 43static void HandleSignalTaskClose_(const LoopHandle loopHandle, const TaskHandle signalHandle) 44{ 45 BaseTask *task = (BaseTask *)signalHandle; 46 DelTask((EventLoop *)loopHandle, task); 47 CloseTask(loopHandle, task); 48 close(task->taskId.fd); 49} 50 51static void PrintSigset(sigset_t mask) 52{ 53 int cnt = 0; 54 for (int sig = 1; sig < NSIG; sig++) { 55 if (sigismember(&mask, sig)) { 56 cnt++; 57 printf("\t %d(%s)\n", sig, strsignal(sig)); 58 } 59 } 60 if (cnt == 0) { 61 printf("empty signal set\n"); 62 } 63} 64 65static void DumpSignalTaskInfo_(const TaskHandle task) 66{ 67 INIT_CHECK(task != NULL, return); 68 BaseTask *baseTask = (BaseTask *)task; 69 SignalTask *signalTask = (SignalTask *)baseTask; 70 printf("\tfd: %d \n", signalTask->base.taskId.fd); 71 printf("\t TaskType: %s \n", "SignalTask"); 72 printf("\t sigNumber: %d \n", signalTask->sigNumber); 73 printf("\t signal: \n"); 74 PrintSigset(signalTask->mask); 75} 76 77LE_STATUS LE_CreateSignalTask(const LoopHandle loopHandle, SignalHandle *signalHandle, LE_ProcessSignal processSignal) 78{ 79 LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); 80 LE_CHECK(processSignal != NULL, return LE_FAILURE, "Invalid parameters processSignal"); 81 sigset_t mask; 82 sigemptyset(&mask); 83 int sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); 84 LE_CHECK(sfd > 0, return -1, "Failed to create signal fd"); 85 LE_BaseInfo info = {TASK_SIGNAL, NULL}; 86 SignalTask *task = (SignalTask *)CreateTask(loopHandle, sfd, &info, sizeof(SignalTask)); 87 LE_CHECK(task != NULL, return LE_NO_MEMORY, "Failed to create task"); 88 task->base.handleEvent = HandleSignalEvent_; 89 task->base.innerClose = HandleSignalTaskClose_; 90 task->base.dumpTaskInfo = DumpSignalTaskInfo_; 91 task->sigNumber = 0; 92 sigemptyset(&task->mask); 93 task->processSignal = processSignal; 94 *signalHandle = (SignalHandle)task; 95 return LE_SUCCESS; 96} 97 98LE_STATUS LE_AddSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal) 99{ 100 LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); 101 EventLoop *loop = (EventLoop *)loopHandle; 102 SignalTask *task = (SignalTask *)signalHandle; 103 LE_LOGI("LE_AddSignal %d %d", signal, task->sigNumber); 104 if (sigismember(&task->mask, signal)) { 105 return LE_SUCCESS; 106 } 107 sigaddset(&task->mask, signal); 108 sigprocmask(SIG_BLOCK, &task->mask, NULL); 109 int sfd = signalfd(GetSocketFd(signalHandle), &task->mask, SFD_NONBLOCK | SFD_CLOEXEC); 110 LE_CHECK(sfd > 0, return -1, "Failed to create signal fd"); 111 if (task->sigNumber == 0) { 112 loop->addEvent(loop, (const BaseTask *)task, EVENT_READ); 113 } else { 114 loop->modEvent(loop, (const BaseTask *)task, EVENT_READ); 115 } 116 task->sigNumber++; 117 return LE_SUCCESS; 118} 119 120LE_STATUS LE_RemoveSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal) 121{ 122 LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); 123 EventLoop *loop = (EventLoop *)loopHandle; 124 SignalTask *task = (SignalTask *)signalHandle; 125 LE_LOGI("LE_RemoveSignal %d %d", signal, task->sigNumber); 126 if (!sigismember(&task->mask, signal)) { 127 return LE_SUCCESS; 128 } 129 sigdelset(&task->mask, signal); 130 task->sigNumber--; 131 int sfd = signalfd(GetSocketFd(signalHandle), &task->mask, SFD_NONBLOCK | SFD_CLOEXEC); 132 LE_CHECK(sfd > 0, return -1, "Failed to create signal fd"); 133 if (task->sigNumber <= 0) { 134 loop->delEvent(loop, GetSocketFd(signalHandle), EVENT_READ); 135 } 136 return LE_SUCCESS; 137} 138 139void LE_CloseSignalTask(const LoopHandle loopHandle, const SignalHandle signalHandle) 140{ 141 LE_CHECK(loopHandle != NULL && signalHandle != NULL, return, "Invalid parameters"); 142 LE_CloseTask(loopHandle, signalHandle); 143} 144