LogCabin
Event/Signal.cc
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines