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
);
105 static void *sig_thread(void *arg
)
107 SignalThread
*context
= (SignalThread
*)arg
;
112 while (context
->get_shutdown() == SHUTDOWN_RUNNING
)
116 if (context
->wait(sig
) == -1)
118 Error
<< "sigwait() returned errno:" << strerror(errno
);
128 if (context
->is_shutdown() == false)
130 context
->set_shutdown(SHUTDOWN_FORCED
);
135 Error
<< "Signal handling thread got unexpected signal " << strsignal(sig
);
145 SignalThread::SignalThread() :
146 magic_memory(MAGIC_MEMORY
),
147 thread(pthread_self())
149 pthread_mutex_init(&shutdown_mutex
, NULL
);
151 if (not getenv("LIBTEST_IN_GDB"))
153 sigaddset(&set
, SIGABRT
);
154 sigaddset(&set
, SIGQUIT
);
155 sigaddset(&set
, SIGINT
);
158 sigaddset(&set
, SIGUSR2
);
160 sem_init(&lock
, 0, 0);
164 bool SignalThread::setup()
166 set_shutdown(SHUTDOWN_RUNNING
);
169 sigemptyset(&old_set
);
170 pthread_sigmask(SIG_BLOCK
, NULL
, &old_set
);
172 if (sigismember(&old_set
, SIGQUIT
))
174 Error
<< strsignal(SIGQUIT
) << " has been previously set.";
176 if (sigismember(&old_set
, SIGINT
))
178 Error
<< strsignal(SIGINT
) << " has been previously set.";
180 if (sigismember(&old_set
, SIGUSR2
))
182 Error
<< strsignal(SIGUSR2
) << " has been previously set.";
186 if ((error
= pthread_sigmask(SIG_BLOCK
, &set
, NULL
)) != 0)
188 Error
<< "pthread_sigmask() died during pthread_sigmask(" << strerror(error
) << ")";
192 if ((error
= pthread_create(&thread
, NULL
, &sig_thread
, this)) != 0)
194 Error
<< "pthread_create() died during pthread_create(" << strerror(error
) << ")";