libzypp 17.37.10

unixsignalsource.cpp
Go to the documentation of this file.
1#include "unixsignalsource.h"
2#include "private/abstracteventsource_p.h"
3#include <zypp-core/AutoDispose.h>
4#include <zypp-core/base/Errno.h>
5#include <zypp-core/base/Logger.h>
6#include <unordered_map>
7
8#include <sys/signalfd.h>
9#include <signal.h>
10
11 namespace zyppng {
12
13 class UnixSignalSourcePrivate : public AbstractEventSourcePrivate
14 {
15 ZYPP_DECLARE_PUBLIC(UnixSignalSource)
16 public:
17 UnixSignalSourcePrivate( UnixSignalSource &p ) : AbstractEventSourcePrivate(p) {
18 ::sigemptyset ( &_orgSigMask );
19 pthread_sigmask (SIG_SETMASK, nullptr, &_orgSigMask);
20 }
21
22 sigset_t _orgSigMask;
23 zypp::AutoFD _signalFd;
24 std::unordered_map<int, int> _signalRefCount;
25 Signal<void (int)> _sigReceived;
26 };
27
28 ZYPP_IMPL_PRIVATE (UnixSignalSource);
29
30 UnixSignalSource::UnixSignalSource() : AbstractEventSource( *(new UnixSignalSourcePrivate(*this)) )
31 {
32 }
33
34 UnixSignalSource::~UnixSignalSource()
35 {
36 Z_D();
37 // restore the original sigmask
38 pthread_sigmask (SIG_SETMASK, &d->_orgSigMask, nullptr);
39 }
40
41 UnixSignalSourceRef UnixSignalSource::create()
42 {
43 return UnixSignalSourceRef( new UnixSignalSource() );
44 }
45
46 bool UnixSignalSource::addSignal(int signum )
47 {
48 Z_D();
49
50 if ( d->_signalRefCount.count(signum) != 0 && d->_signalRefCount[signum] > 0 ) {
51 // we already handle this signal, just increase refcount
52 d->_signalRefCount[signum]++;
53 } else {
54
55 const auto &handleError = [&]() {
56 d->_signalRefCount.erase ( signum );
57 return false;
58 };
59
60 // add the signal to our map
61 d->_signalRefCount[signum] = 1;
62
63 sigset_t sigMask;
64 sigemptyset (&sigMask );
65
66 // add all the signals we monitor to our set so we can update the signalfd correctly
67 for ( const auto &sig : d->_signalRefCount ) {
68 sigaddset(&sigMask, sig.first);
69 }
70
71 // signalfd signals should be blocked
72 // man page says: The set of blocked signals is the union of the current set and the set argument.
73 // so we should not accidentially delete other blocks done by the application
74 if (pthread_sigmask (SIG_BLOCK, &sigMask, NULL) == -1) {
75 return handleError();
76 }
77
78
79 // set or update our signal fd
80 zypp::AutoFD aFd = signalfd ( d->_signalFd, &sigMask, SFD_NONBLOCK | SFD_CLOEXEC );
81 if ( aFd == -1 ){
82 return handleError();
83 }
84
85 if ( d->_signalFd != aFd ) {
86 d->_signalFd = aFd;
87 } else {
88 aFd.resetDispose ();
89 }
90 updateFdWatch ( aFd, AbstractEventSource::Read );
91 }
92 return true;
93 }
94
95 bool UnixSignalSource::removeSignal(int signum )
96 {
97 Z_D();
98 if ( !d->_signalRefCount.count(signum) || d->_signalRefCount[signum] == 0 ) {
99 return true;
100 }
101 d->_signalRefCount[signum]--;
102
103 if ( d->_signalRefCount[signum] <= 0 ) {
104
105 d->_signalRefCount.erase(signum);
106
107 // remove the signal from our fd
108 sigset_t sigMask;
109 sigemptyset ( &sigMask );
110 for ( const auto &sig : d->_signalRefCount ) {
111 sigaddset(&sigMask, sig.first);
112 }
113
114 auto res = signalfd ( d->_signalFd, &sigMask, SFD_NONBLOCK | SFD_CLOEXEC );
115 if ( res == -1 ) {
116 WAR << "Failed to update signalfd with errno: " << zypp::Errno() << std::endl;
117 return false;
118 }
119
120 // unblock the signal
121 sigemptyset ( &sigMask );
122 sigaddset(&sigMask, signum);
123 pthread_sigmask(SIG_UNBLOCK, &sigMask, NULL);
124 }
125
126 if ( d->_signalRefCount.size () == 0 ) {
127 removeFdWatch ( d->_signalFd );
128 d->_signalFd = -1;
129 }
130 return true;
131 }
132
133 SignalProxy<void (int)> UnixSignalSource::sigReceived()
134 {
135 return d_func()->_sigReceived;
136 }
137
138 void zyppng::UnixSignalSource::onFdReady( int fd, int events )
139 {
140 Z_D();
141 struct signalfd_siginfo sfd_si;
142 if ( read(fd, &sfd_si, sizeof(sfd_si)) == -1 ) {
143 WAR << "Failed to read from signalfd" << std::endl;
144 return;
145 }
146
147 if ( d->_signalRefCount.count ( sfd_si.ssi_signo ))
148 d->_sigReceived.emit( sfd_si.ssi_signo );
149 else
150 WAR << "Received unexpected UNIX signal on signalFD: " << sfd_si.ssi_signo << std::endl;
151 }
152
153 void zyppng::UnixSignalSource::onSignal( int signal )
154 {}
155
156} // namespace zyppng
abstracteventsource_p.h
zypp::AutoDispose::resetDispose
void resetDispose()
Set no dispose function.
Definition AutoDispose.h:171
zypp::Errno
Convenience errno wrapper.
Definition Errno.h:26
zyppng::AbstractEventSourcePrivate::AbstractEventSourcePrivate
AbstractEventSourcePrivate(AbstractEventSource &p)
Definition abstracteventsource.cc:10
zyppng::AbstractEventSource::AbstractEventSource
AbstractEventSource()
Definition abstracteventsource.cc:20
zyppng::AbstractEventSource::Read
@ Read
Definition abstracteventsource.h:47
zyppng::AbstractEventSource::updateFdWatch
void updateFdWatch(int fd, int mode)
Definition abstracteventsource.cc:42
zyppng::AbstractEventSource::removeFdWatch
void removeFdWatch(int fd)
Definition abstracteventsource.cc:52
zyppng::SignalProxy
Definition signals.h:325
zyppng::Signal
Definition signals.h:151
zyppng::UnixSignalSourcePrivate
Definition unixsignalsource.cpp:14
zyppng::UnixSignalSourcePrivate::_orgSigMask
sigset_t _orgSigMask
Definition unixsignalsource.cpp:22
zyppng::UnixSignalSourcePrivate::_signalFd
zypp::AutoFD _signalFd
Definition unixsignalsource.cpp:23
zyppng::UnixSignalSourcePrivate::_signalRefCount
std::unordered_map< int, int > _signalRefCount
Definition unixsignalsource.cpp:24
zyppng::UnixSignalSourcePrivate::UnixSignalSourcePrivate
UnixSignalSourcePrivate(UnixSignalSource &p)
Definition unixsignalsource.cpp:17
zyppng::UnixSignalSourcePrivate::_sigReceived
Signal< void(int)> _sigReceived
Definition unixsignalsource.cpp:25
zyppng::UnixSignalSource
Definition unixsignalsource.h:13
zyppng::UnixSignalSource::addSignal
bool addSignal(int signum)
Definition unixsignalsource.cpp:46
zyppng::UnixSignalSource::onFdReady
void onFdReady(int fd, int events) override
Definition unixsignalsource.cpp:138
zyppng::UnixSignalSource::UnixSignalSource
UnixSignalSource()
Definition unixsignalsource.cpp:30
zyppng::UnixSignalSource::removeSignal
bool removeSignal(int signum)
Definition unixsignalsource.cpp:95
zyppng::UnixSignalSource::create
static UnixSignalSourceRef create()
Definition unixsignalsource.cpp:41
zyppng::UnixSignalSource::~UnixSignalSource
~UnixSignalSource() override
Definition unixsignalsource.cpp:34
zyppng::UnixSignalSource::onSignal
void onSignal(int signal) override
Definition unixsignalsource.cpp:153
zyppng::UnixSignalSource::sigReceived
SignalProxy< void(int signum)> sigReceived()
Definition unixsignalsource.cpp:133
zyppng
Definition MediaNetworkRequestExecutor.h:16
zypp::AutoFD
AutoDispose<int> calling close
Definition AutoDispose.h:310
unixsignalsource.h
AutoDispose.h
Errno.h
Logger.h
WAR
#define WAR
Definition Logger.h:101
ZYPP_IMPL_PRIVATE
#define ZYPP_IMPL_PRIVATE(Class)
Definition zyppglobal.h:92
Z_D
#define Z_D()
Definition zyppglobal.h:105
ZYPP_DECLARE_PUBLIC
#define ZYPP_DECLARE_PUBLIC(Class)
Definition zyppglobal.h:98