1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32 #include <util/signal.hpp>
34 namespace datadifferential
{
37 #define MAGIC_MEMORY 123569
39 bool SignalThread::is_shutdown()
42 pthread_mutex_lock(&shutdown_mutex
);
43 ret
= bool(__shutdown
!= SHUTDOWN_RUNNING
);
44 pthread_mutex_unlock(&shutdown_mutex
);
49 void SignalThread::set_shutdown(shutdown_t arg
)
51 pthread_mutex_lock(&shutdown_mutex
);
53 pthread_mutex_unlock(&shutdown_mutex
);
55 if (arg
== SHUTDOWN_GRACEFUL
)
57 if (pthread_kill(thread
, SIGUSR2
) == 0)
60 pthread_join(thread
, &retval
);
65 shutdown_t
SignalThread::get_shutdown()
68 pthread_mutex_lock(&shutdown_mutex
);
70 pthread_mutex_unlock(&shutdown_mutex
);
75 void SignalThread::post()
80 void SignalThread::test()
82 assert(magic_memory
== MAGIC_MEMORY
);
83 assert(sigismember(&set
, SIGABRT
));
84 assert(sigismember(&set
, SIGINT
));
85 assert(sigismember(&set
, SIGQUIT
));
86 assert(sigismember(&set
, SIGTERM
));
87 assert(sigismember(&set
, SIGUSR2
));
90 SignalThread::~SignalThread()
92 if (not is_shutdown())
94 set_shutdown(SHUTDOWN_GRACEFUL
);
98 if (pthread_equal(thread
, pthread_self()) != 0 and (pthread_kill(thread
, 0) == ESRCH
) == true)
101 pthread_join(thread
, &retval
);
109 static void *sig_thread(void *arg
)
111 SignalThread
*context
= (SignalThread
*)arg
;
116 while (context
->get_shutdown() == SHUTDOWN_RUNNING
)
120 if (context
->wait(sig
) == -1)
122 std::cerr
<< "sigwait() returned errno:" << strerror(errno
) << std::endl
;
135 if (context
->is_shutdown() == false)
137 context
->set_shutdown(SHUTDOWN_FORCED
);
140 if (context
->exit_on_signal())
148 std::cerr
<< "Signal handling thread got unexpected signal " << strsignal(sig
) << std::endl
;
158 SignalThread::SignalThread(bool exit_on_signal_arg
) :
159 _exit_on_signal(exit_on_signal_arg
),
160 magic_memory(MAGIC_MEMORY
),
161 thread(pthread_self())
163 pthread_mutex_init(&shutdown_mutex
, NULL
);
166 sigaddset(&set
, SIGABRT
);
167 sigaddset(&set
, SIGINT
);
168 sigaddset(&set
, SIGQUIT
);
169 sigaddset(&set
, SIGTERM
);
170 sigaddset(&set
, SIGUSR2
);
172 sem_init(&lock
, 0, 0);
176 bool SignalThread::setup()
178 set_shutdown(SHUTDOWN_RUNNING
);
181 if ((error
= pthread_sigmask(SIG_BLOCK
, &set
, NULL
)) != 0)
183 std::cerr
<< "pthread_sigmask() died during pthread_sigmask(" << strerror(error
) << ")" << std::endl
;
187 if ((error
= pthread_create(&thread
, NULL
, &sig_thread
, this)) != 0)
189 std::cerr
<< "pthread_create() died during pthread_create(" << strerror(error
) << ")" << std::endl
;
198 } /* namespace util */
199 } /* namespace datadifferential */