2
Copyright (C) 2011 Brian Aker
3
Copyright (C) 2006 MySQL AB
1
/* Copyright (C) 2006 MySQL AB
5
3
This program is free software; you can redistribute it and/or modify
6
4
it under the terms of the GNU General Public License as published by
15
13
along with this program; if not, write to the Free Software
16
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
20
17
#include <drizzled/gettext.h>
21
18
#include <drizzled/error.h>
22
19
#include <drizzled/unireg.h>
23
20
#include <drizzled/plugin/storage_engine.h>
24
#include <drizzled/pthread_globals.h>
25
#include <drizzled/internal/my_pthread.h>
26
#include <drizzled/internal/my_sys.h>
27
#include <drizzled/plugin/daemon.h>
28
#include <drizzled/signal_handler.h>
30
#include <drizzled/session.h>
31
#include <drizzled/session/cache.h>
33
#include <drizzled/debug.h>
35
#include <drizzled/drizzled.h>
37
#include <drizzled/refresh_version.h>
39
#include <boost/thread/thread.hpp>
40
#include <boost/filesystem.hpp>
21
#include <drizzled/cursor.h> /* for refresh_version */
22
#include "drizzled/pthread_globals.h"
23
#include "drizzled/internal/my_pthread.h"
24
#include "drizzled/internal/my_sys.h"
25
#include "drizzled/plugin/daemon.h"
26
#include "drizzled/signal_handler.h"
28
#include "drizzled/drizzled.h"
42
30
#include <sys/stat.h>
46
34
static bool kill_in_progress= false;
47
void signal_hand(void);
35
extern "C" pthread_handler_t signal_hand(void *);
51
39
extern int cleanup_done;
52
40
extern bool volatile abort_loop;
53
41
extern bool volatile shutdown_in_progress;
54
extern boost::filesystem::path pid_file;
42
extern char pidfile_name[FN_REFLEN];
55
43
/* Prototypes -> all of these should be factored out into a propper shutdown */
56
44
extern void close_connections(void);
45
extern std::bitset<12> test_flags;
59
48
using namespace drizzled;
65
53
Force server down. Kill all connections and threads and exit.
72
60
or stop, we just want to kill the server.
75
static void kill_server(int sig)
63
static void kill_server(void *sig_ptr)
65
int sig=(int) (long) sig_ptr; // This is passed a int
77
66
// if there is a signal during the kill in progress, ignore the other
78
67
if (kill_in_progress) // Safety
82
71
if (sig != 0) // 0 is not a valid signal number
83
72
ignore_signal(sig); /* purify inspected */
84
73
if (sig == SIGTERM || sig == 0)
85
errmsg_printf(error::INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
74
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
87
errmsg_printf(error::ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
76
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
89
77
close_connections();
112
101
(void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
114
memset(buff, 0, sizeof(buff));
115
snprintf(buff, sizeof(buff)-1, "Can't start server: can't create PID file (%s)", pid_file.file_string().c_str());
103
snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
116
104
sql_perror(buff);
121
109
/** This threads handles all signals and alarms. */
110
pthread_handler_t signal_hand(void *)
126
114
internal::my_thread_init(); // Init new thread
127
boost::this_thread::at_thread_exit(&internal::my_thread_end);
128
115
signal_thread_in_use= true;
130
if ((drizzled::getDebug().test(drizzled::debug::ALLOW_SIGINT)))
117
if ((test_flags.test(TEST_SIGINT)))
132
119
(void) sigemptyset(&set); // Setup up SIGINT for debug
133
120
(void) sigaddset(&set,SIGINT); // For debugging
134
(void) pthread_sigmask(SIG_UNBLOCK, &set, NULL);
121
(void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
136
123
(void) sigemptyset(&set); // Setup up SIGINT for debug
137
124
#ifndef IGNORE_SIGHUP_SIGQUIT
138
if (sigaddset(&set,SIGQUIT))
140
std::cerr << "failed setting sigaddset() with SIGQUIT\n";
142
if (sigaddset(&set,SIGHUP))
144
std::cerr << "failed setting sigaddset() with SIGHUP\n";
125
(void) sigaddset(&set,SIGQUIT);
126
(void) sigaddset(&set,SIGHUP);
147
if (sigaddset(&set,SIGTERM))
149
std::cerr << "failed setting sigaddset() with SIGTERM\n";
151
if (sigaddset(&set,SIGTSTP))
153
std::cerr << "failed setting sigaddset() with SIGTSTP\n";
128
(void) sigaddset(&set,SIGTERM);
129
(void) sigaddset(&set,SIGTSTP);
156
131
/* Save pid to this process (or thread on Linux) */
157
132
create_pid_file();
168
143
(Asked MontyW over the phone about this.) -Brian
171
session::Cache::singleton().mutex().lock();
172
session::Cache::singleton().mutex().unlock();
146
LOCK_thread_count.lock();
147
LOCK_thread_count.unlock();
173
148
COND_thread_count.notify_all();
175
if (pthread_sigmask(SIG_BLOCK, &set, NULL))
177
std::cerr << "Failed to set pthread_sigmask() in signal handler\n";
150
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
182
153
int error; // Used when debugging
184
154
if (shutdown_in_progress && !abort_loop)
191
while ((error= sigwait(&set, &sig)) == EINTR) ;
160
while ((error= sigwait(&set,&sig)) == EINTR) ;
194
161
if (cleanup_done)
163
internal::my_thread_end();
196
164
signal_thread_in_use= false;
205
172
/* switch to the old log message processing */
208
175
abort_loop=1; // mark abort for threads
209
kill_server(sig); // MIT THREAD has a alarm thread
176
kill_server((void*) sig); // MIT THREAD has a alarm thread
228
195
SignalHandler(const SignalHandler &);
229
196
SignalHandler& operator=(const SignalHandler &);
230
boost::thread thread;
234
drizzled::plugin::Daemon("Signal Handler")
199
: drizzled::plugin::Daemon("Signal Handler")
202
pthread_attr_t thr_attr;
203
size_t my_thread_stack_size= 65536;
205
(void) pthread_attr_init(&thr_attr);
206
pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
207
(void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
209
struct sched_param tmp_sched_param;
211
memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
212
tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
213
(void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
215
#if defined(__ia64__) || defined(__ia64)
217
Peculiar things with ia64 platforms - it seems we only have half the
218
stack size in reality, so we have to double it here
220
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
222
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
236
225
// @todo fix spurious wakeup issue
237
boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
238
thread= boost::thread(signal_hand);
239
signal_thread= thread.native_handle();
240
COND_thread_count.wait(scopedLock);
226
(void) LOCK_thread_count.lock();
227
if ((error= pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
229
errmsg_printf(ERRMSG_LVL_ERROR,
230
_("Can't create interrupt-thread (error %d, errno: %d)"),
234
pthread_cond_wait(COND_thread_count.native_handle(), LOCK_thread_count.native_handle());
235
LOCK_thread_count.unlock();
237
(void) pthread_attr_destroy(&thr_attr);
250
247
Wait up to 100000 micro-seconds for signal thread to die. We use this mainly to
251
248
avoid getting warnings that internal::my_thread_end has not been called
253
bool completed= false;
255
* We send SIGTERM and then do a timed join. If that fails we will on
256
* the last pthread_kill() call SIGTSTP. OSX (and FreeBSD) seem to
257
* prefer this. -Brian
259
uint32_t count= 2; // How many times to try join and see if the caller died.
260
while (not completed and count--)
250
for (uint32_t i= 0 ; i < 100 && signal_thread_in_use; i++)
263
int signal= count == 1 ? SIGTSTP : SIGTERM;
265
if ((error= pthread_kill(thread.native_handle(), signal)))
267
char buffer[1024]; // No reason for number;
268
strerror_r(error, buffer, sizeof(buffer));
269
std::cerr << "pthread_kill() error on shutdown of signal thread (" << buffer << ")\n";
252
if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
274
boost::posix_time::milliseconds duration(100);
275
completed= thread.timed_join(duration);
259
nanosleep(&tm, NULL); // Give it time to die
281
265
static int init(drizzled::module::Context& context)
283
context.add(new SignalHandler);
267
SignalHandler *handler= new SignalHandler;
268
context.add(handler);
273
static drizzle_sys_var* system_variables[]= {
289
277
DRIZZLE_DECLARE_PLUGIN
291
279
DRIZZLE_VERSION_ID,