LogCabin
|
00001 /* Copyright (c) 2011-2014 Stanford University 00002 * Copyright (c) 2015 Diego Ongaro 00003 * 00004 * Permission to use, copy, modify, and distribute this software for any 00005 * purpose with or without fee is hereby granted, provided that the above 00006 * copyright notice and this permission notice appear in all copies. 00007 * 00008 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00009 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00010 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR 00011 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00012 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00013 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00014 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 */ 00016 00017 #include <cstring> 00018 #include <signal.h> 00019 #include <sys/epoll.h> 00020 #include <sys/signalfd.h> 00021 #include <unistd.h> 00022 00023 #include "Core/Debug.h" 00024 #include "Event/Loop.h" 00025 #include "Event/Signal.h" 00026 00027 namespace LogCabin { 00028 namespace Event { 00029 00030 namespace { 00031 00032 /// Helper for Signal constructor. 00033 int 00034 createSignalFd(int signalNumber) 00035 { 00036 sigset_t mask; 00037 sigemptyset(&mask); 00038 sigaddset(&mask, signalNumber); 00039 int fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); 00040 if (fd < 0) { 00041 PANIC("Could not create signalfd for signal %d: %s", 00042 signalNumber, strerror(errno)); 00043 } 00044 return fd; 00045 } 00046 00047 } // anonymous namespace 00048 00049 //// class Signal::Blocker //// 00050 00051 Signal::Blocker::Blocker(int signalNumber) 00052 : signalNumber(signalNumber) 00053 , isBlocked(false) 00054 , shouldLeaveBlocked(false) 00055 { 00056 block(); 00057 } 00058 00059 Signal::Blocker::~Blocker() 00060 { 00061 if (!shouldLeaveBlocked) 00062 unblock(); 00063 } 00064 00065 void 00066 Signal::Blocker::block() 00067 { 00068 if (!isBlocked) { 00069 sigset_t mask; 00070 sigemptyset(&mask); 00071 sigaddset(&mask, signalNumber); 00072 int r = pthread_sigmask(SIG_BLOCK, &mask, NULL); 00073 if (r != 0) { 00074 PANIC("Could not block signal %d: %s", 00075 signalNumber, strerror(r)); 00076 } 00077 isBlocked = true; 00078 } 00079 } 00080 00081 void 00082 Signal::Blocker::leaveBlocked() 00083 { 00084 shouldLeaveBlocked = true; 00085 } 00086 00087 void 00088 Signal::Blocker::unblock() 00089 { 00090 if (isBlocked) { 00091 sigset_t mask; 00092 sigemptyset(&mask); 00093 sigaddset(&mask, signalNumber); 00094 int r = pthread_sigmask(SIG_UNBLOCK, &mask, NULL); 00095 if (r != 0) { 00096 PANIC("Could not unblock signal %d: %s", 00097 signalNumber, strerror(r)); 00098 } 00099 isBlocked = false; 00100 shouldLeaveBlocked = false; 00101 } 00102 } 00103 00104 00105 //// class Signal::Monitor //// 00106 00107 Signal::Monitor::Monitor(Event::Loop& eventLoop, Signal& signal) 00108 : File::Monitor(eventLoop, signal, EPOLLIN) 00109 { 00110 } 00111 00112 Signal::Monitor::~Monitor() 00113 { 00114 } 00115 00116 00117 //// class Signal //// 00118 00119 Signal::Signal(int signalNumber) 00120 : Event::File(createSignalFd(signalNumber)) 00121 , signalNumber(signalNumber) 00122 { 00123 } 00124 00125 Signal::~Signal() 00126 { 00127 } 00128 00129 void 00130 Signal::handleFileEvent(uint32_t events) 00131 { 00132 struct signalfd_siginfo info; 00133 ssize_t s = read(fd, &info, sizeof(struct signalfd_siginfo)); 00134 if (s < 0) { 00135 PANIC("Could not read signal info (to discard): %s", 00136 strerror(errno)); 00137 } 00138 if (size_t(s) != sizeof(struct signalfd_siginfo)) { 00139 PANIC("Could not read full signal info (to discard)"); 00140 } 00141 handleSignalEvent(); 00142 } 00143 00144 } // namespace LogCabin::Event 00145 } // namespace LogCabin