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
23 #include <libtest/common.h>
27 #include <libtest/signal.h>
29 using namespace libtest
;
31 #define MAGIC_MEMORY 123569
33 bool SignalThread::is_shutdown()
36 pthread_mutex_lock(&shutdown_mutex
);
37 ret
= bool(__shutdown
!= SHUTDOWN_RUNNING
);
38 pthread_mutex_unlock(&shutdown_mutex
);
43 void SignalThread::set_shutdown(shutdown_t arg
)
45 pthread_mutex_lock(&shutdown_mutex
);
47 pthread_mutex_unlock(&shutdown_mutex
);
49 if (arg
== SHUTDOWN_GRACEFUL
)
51 if (pthread_kill(thread
, SIGUSR2
) == 0)
54 pthread_join(thread
, &retval
);
59 shutdown_t
SignalThread::get_shutdown()
62 pthread_mutex_lock(&shutdown_mutex
);
64 pthread_mutex_unlock(&shutdown_mutex
);
69 void SignalThread::post()
74 void SignalThread::test()
76 assert(magic_memory
== MAGIC_MEMORY
);
77 if (not getenv("LIBTEST_IN_GDB"))
79 assert(sigismember(&set
, SIGABRT
));
80 assert(sigismember(&set
, SIGQUIT
));
81 assert(sigismember(&set
, SIGINT
));
83 assert(sigismember(&set
, SIGUSR2
));
86 SignalThread::~SignalThread()
88 if (not is_shutdown())
90 set_shutdown(SHUTDOWN_GRACEFUL
);
94 if (pthread_equal(thread
, pthread_self()) != 0 and (pthread_kill(thread
, 0) == ESRCH
) == true)
97 pthread_join(thread
, &retval
);
103 if ((error
= pthread_sigmask(SIG_UNBLOCK
, &set
, NULL
)) != 0)
105 Error
<< "While trying to reset signal mask to original set, pthread_sigmask() died during pthread_sigmask(" << strerror(error
) << ")";
111 static void *sig_thread(void *arg
)
113 SignalThread
*context
= (SignalThread
*)arg
;
118 while (context
->get_shutdown() == SHUTDOWN_RUNNING
)
122 if (context
->wait(sig
) == -1)
124 Error
<< "sigwait() returned errno:" << strerror(errno
);
134 if (context
->is_shutdown() == false)
136 context
->set_shutdown(SHUTDOWN_FORCED
);
141 Error
<< "Ignoring SIGPIPE";
146 Error
<< "Signal handling thread got unexpected signal " << strsignal(sig
);
156 SignalThread::SignalThread() :
157 magic_memory(MAGIC_MEMORY
),
158 thread(pthread_self())
160 pthread_mutex_init(&shutdown_mutex
, NULL
);
162 if (not getenv("LIBTEST_IN_GDB"))
164 sigaddset(&set
, SIGABRT
);
165 sigaddset(&set
, SIGQUIT
);
166 sigaddset(&set
, SIGINT
);
168 sigaddset(&set
, SIGPIPE
);
170 sigaddset(&set
, SIGUSR2
);
172 sem_init(&lock
, 0, 0);
174 sigemptyset(&original_set
);
175 pthread_sigmask(SIG_BLOCK
, NULL
, &original_set
);
179 bool SignalThread::setup()
181 set_shutdown(SHUTDOWN_RUNNING
);
183 if (sigismember(&original_set
, SIGQUIT
))
185 Error
<< strsignal(SIGQUIT
) << " has been previously set.";
187 if (sigismember(&original_set
, SIGINT
))
189 Error
<< strsignal(SIGINT
) << " has been previously set.";
191 if (sigismember(&original_set
, SIGUSR2
))
193 Error
<< strsignal(SIGUSR2
) << " has been previously set.";
197 if ((error
= pthread_sigmask(SIG_BLOCK
, &set
, NULL
)) != 0)
199 Error
<< "pthread_sigmask() died during pthread_sigmask(" << strerror(error
) << ")";
203 if ((error
= pthread_create(&thread
, NULL
, &sig_thread
, this)) != 0)
205 Error
<< "pthread_create() died during pthread_create(" << strerror(error
) << ")";