25
25
#include "drizzled/plugin/daemon.h"
26
26
#include "drizzled/signal_handler.h"
28
#include "drizzled/session/cache.h"
30
#include "drizzled/drizzled.h"
32
#include <boost/thread/thread.hpp>
33
#include <boost/filesystem.hpp>
35
28
#include <sys/stat.h>
39
32
static bool kill_in_progress= false;
40
void signal_hand(void);
33
static bool volatile signal_thread_in_use= false;
34
extern "C" pthread_handler_t signal_hand(void *);
44
38
extern int cleanup_done;
45
39
extern bool volatile abort_loop;
46
40
extern bool volatile shutdown_in_progress;
47
extern boost::filesystem::path pid_file;
41
extern char pidfile_name[FN_REFLEN];
48
42
/* Prototypes -> all of these should be factored out into a propper shutdown */
49
43
extern void close_connections(void);
50
44
extern std::bitset<12> test_flags;
66
59
or stop, we just want to kill the server.
69
static void kill_server(int sig)
62
static void kill_server(void *sig_ptr)
64
int sig=(int) (long) sig_ptr; // This is passed a int
71
65
// if there is a signal during the kill in progress, ignore the other
72
66
if (kill_in_progress) // Safety
79
73
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
81
75
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
82
77
close_connections();
78
if (sig != SIGTERM && sig != 0)
105
104
(void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
107
memset(buff, 0, sizeof(buff));
108
snprintf(buff, sizeof(buff)-1, "Can't start server: can't create PID file (%s)", pid_file.file_string().c_str());
106
snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
109
107
sql_perror(buff);
114
112
/** This threads handles all signals and alarms. */
113
pthread_handler_t signal_hand(void *)
119
117
internal::my_thread_init(); // Init new thread
120
boost::this_thread::at_thread_exit(&internal::my_thread_end);
121
118
signal_thread_in_use= true;
123
if ((test_flags.test(TEST_SIGINT)))
120
if (internal::thd_lib_detected != THD_LIB_LT &&
121
(test_flags.test(TEST_SIGINT)))
125
123
(void) sigemptyset(&set); // Setup up SIGINT for debug
126
124
(void) sigaddset(&set,SIGINT); // For debugging
129
127
(void) sigemptyset(&set); // Setup up SIGINT for debug
130
128
#ifndef IGNORE_SIGHUP_SIGQUIT
131
if (sigaddset(&set,SIGQUIT))
133
std::cerr << "failed setting sigaddset() with SIGQUIT\n";
135
if (sigaddset(&set,SIGHUP))
137
std::cerr << "failed setting sigaddset() with SIGHUP\n";
129
(void) sigaddset(&set,SIGQUIT);
130
(void) sigaddset(&set,SIGHUP);
140
if (sigaddset(&set,SIGTERM))
142
std::cerr << "failed setting sigaddset() with SIGTERM\n";
144
if (sigaddset(&set,SIGTSTP))
146
std::cerr << "failed setting sigaddset() with SIGTSTP\n";
132
(void) sigaddset(&set,SIGTERM);
133
(void) sigaddset(&set,SIGTSTP);
149
135
/* Save pid to this process (or thread on Linux) */
150
136
create_pid_file();
161
147
(Asked MontyW over the phone about this.) -Brian
164
session::Cache::singleton().mutex().lock();
165
session::Cache::singleton().mutex().unlock();
166
COND_thread_count.notify_all();
168
if (pthread_sigmask(SIG_BLOCK, &set, NULL))
170
std::cerr << "Failed to set pthread_sigmask() in signal handler\n";
150
if (pthread_mutex_lock(&LOCK_thread_count) == 0)
151
(void) pthread_mutex_unlock(&LOCK_thread_count);
152
(void) pthread_cond_broadcast(&COND_thread_count);
154
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
175
157
int error; // Used when debugging
177
158
if (shutdown_in_progress && !abort_loop)
184
while ((error= sigwait(&set, &sig)) == EINTR) ;
164
while ((error= sigwait(&set,&sig)) == EINTR) ;
187
165
if (cleanup_done)
167
internal::my_thread_end();
189
168
signal_thread_in_use= false;
198
176
/* switch to the old log message processing */
201
179
abort_loop=1; // mark abort for threads
202
kill_server(sig); // MIT THREAD has a alarm thread
180
kill_server((void*) sig); // MIT THREAD has a alarm thread
221
199
SignalHandler(const SignalHandler &);
222
200
SignalHandler& operator=(const SignalHandler &);
223
boost::thread thread;
227
drizzled::plugin::Daemon("Signal Handler")
203
: drizzled::plugin::Daemon("Signal Handler")
229
// @todo fix spurious wakeup issue
230
boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
231
thread= boost::thread(signal_hand);
232
signal_thread= thread.native_handle();
233
COND_thread_count.wait(scopedLock);
206
pthread_attr_t thr_attr;
207
size_t my_thread_stack_size= 65536;
209
(void) pthread_attr_init(&thr_attr);
210
pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
211
(void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
213
struct sched_param tmp_sched_param;
215
memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
216
tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
217
(void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
219
#if defined(__ia64__) || defined(__ia64)
221
Peculiar things with ia64 platforms - it seems we only have half the
222
stack size in reality, so we have to double it here
224
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
226
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
229
(void) pthread_mutex_lock(&LOCK_thread_count);
230
if ((error=pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
232
errmsg_printf(ERRMSG_LVL_ERROR,
233
_("Can't create interrupt-thread (error %d, errno: %d)"),
237
(void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
238
pthread_mutex_unlock(&LOCK_thread_count);
240
(void) pthread_attr_destroy(&thr_attr);
243
250
Wait up to 100000 micro-seconds for signal thread to die. We use this mainly to
244
251
avoid getting warnings that internal::my_thread_end has not been called
246
bool completed= false;
248
* We send SIGTERM and then do a timed join. If that fails we will on
249
* the last pthread_kill() call SIGTSTP. OSX (and FreeBSD) seem to
250
* prefer this. -Brian
252
uint32_t count= 2; // How many times to try join and see if the caller died.
253
while (not completed and count--)
253
for (uint32_t i= 0 ; i < 100 && signal_thread_in_use; i++)
256
int signal= count == 1 ? SIGTSTP : SIGTERM;
258
if ((error= pthread_kill(thread.native_handle(), signal)))
260
char buffer[1024]; // No reason for number;
261
strerror_r(error, buffer, sizeof(buffer));
262
std::cerr << "pthread_kill() error on shutdown of signal thread (" << buffer << ")\n";
255
if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
267
boost::posix_time::milliseconds duration(100);
268
completed= thread.timed_join(duration);
262
nanosleep(&tm, NULL); // Give it time to die
274
268
static int init(drizzled::module::Context& context)
276
context.add(new SignalHandler);
270
SignalHandler *handler= new SignalHandler;
271
context.add(handler);