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
24 #include <libtest/common.h>
28 #include <libtest/signal.h>
30 using namespace libtest
;
32 #define MAGIC_MEMORY 123569
34 bool SignalThread::is_shutdown()
37 pthread_mutex_lock(&shutdown_mutex
);
38 ret
= bool(__shutdown
!= SHUTDOWN_RUNNING
);
39 pthread_mutex_unlock(&shutdown_mutex
);
44 void SignalThread::set_shutdown(shutdown_t arg
)
46 pthread_mutex_lock(&shutdown_mutex
);
48 pthread_mutex_unlock(&shutdown_mutex
);
50 if (arg
== SHUTDOWN_GRACEFUL
)
52 if (pthread_kill(thread
, SIGUSR2
) == 0)
55 pthread_join(thread
, &retval
);
60 shutdown_t
SignalThread::get_shutdown()
63 pthread_mutex_lock(&shutdown_mutex
);
65 pthread_mutex_unlock(&shutdown_mutex
);
70 void SignalThread::post()
75 void SignalThread::test()
77 assert(magic_memory
== MAGIC_MEMORY
);
78 if (bool(getenv("LIBTEST_IN_GDB")) == false)
80 assert(sigismember(&set
, SIGABRT
));
81 assert(sigismember(&set
, SIGQUIT
));
82 assert(sigismember(&set
, SIGINT
));
84 assert(sigismember(&set
, SIGUSR2
));
87 SignalThread::~SignalThread()
89 if (is_shutdown() == false)
91 set_shutdown(SHUTDOWN_GRACEFUL
);
95 if (pthread_equal(thread
, pthread_self()) != 0 and (pthread_kill(thread
, 0) == ESRCH
) == true)
98 pthread_join(thread
, &retval
);
104 if ((error
= pthread_sigmask(SIG_UNBLOCK
, &set
, NULL
)) != 0)
106 Error
<< "While trying to reset signal mask to original set, pthread_sigmask() died during pthread_sigmask(" << strerror(error
) << ")";
112 static void *sig_thread(void *arg
)
114 SignalThread
*context
= (SignalThread
*)arg
;
119 while (context
->get_shutdown() == SHUTDOWN_RUNNING
)
123 if (context
->wait(sig
) == -1)
125 Error
<< "sigwait() returned errno:" << strerror(errno
);
135 if (context
->is_shutdown() == false)
137 context
->set_shutdown(SHUTDOWN_FORCED
);
142 Error
<< "Ignoring SIGPIPE";
147 Error
<< "Inside of gdb";
151 Error
<< "Signal handling thread got unexpected signal " << strsignal(sig
);
161 SignalThread::SignalThread() :
162 magic_memory(MAGIC_MEMORY
),
163 thread(pthread_self())
165 pthread_mutex_init(&shutdown_mutex
, NULL
);
167 if (bool(getenv("LIBTEST_IN_GDB")) == false)
169 sigaddset(&set
, SIGABRT
);
170 sigaddset(&set
, SIGQUIT
);
171 sigaddset(&set
, SIGINT
);
173 sigaddset(&set
, SIGPIPE
);
175 sigaddset(&set
, SIGUSR2
);
177 sem_init(&lock
, 0, 0);
179 sigemptyset(&original_set
);
180 pthread_sigmask(SIG_BLOCK
, NULL
, &original_set
);
184 bool SignalThread::setup()
186 set_shutdown(SHUTDOWN_RUNNING
);
188 if (sigismember(&original_set
, SIGQUIT
))
190 Error
<< strsignal(SIGQUIT
) << " has been previously set.";
192 if (sigismember(&original_set
, SIGINT
))
194 Error
<< strsignal(SIGINT
) << " has been previously set.";
196 if (sigismember(&original_set
, SIGUSR2
))
198 Error
<< strsignal(SIGUSR2
) << " has been previously set.";
202 if ((error
= pthread_sigmask(SIG_BLOCK
, &set
, NULL
)) != 0)
204 Error
<< "pthread_sigmask() died during pthread_sigmask(" << strerror(error
) << ")";
208 if ((error
= pthread_create(&thread
, NULL
, &sig_thread
, this)) != 0)
210 Error
<< "pthread_create() died during pthread_create(" << strerror(error
) << ")";