25
25
#include "drizzled/plugin/daemon.h"
26
26
#include "drizzled/signal_handler.h"
28
#include "drizzled/session_list.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
Wait up to 100000 micro-seconds for signal thread to die. We use this mainly to
251
Wait up to 10 seconds for signal thread to die. We use this mainly to
244
252
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--)
254
for (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";
256
if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
267
boost::posix_time::milliseconds duration(100);
268
completed= thread.timed_join(duration);
258
usleep(100); // Give it time to die
274
264
static int init(drizzled::module::Context& context)
276
context.add(new SignalHandler);
266
SignalHandler *handler= new SignalHandler;
267
context.add(handler);