13
13
along with this program; if not, write to the Free Software
14
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
#include <drizzled/server_includes.h>
17
17
#include <drizzled/gettext.h>
18
18
#include <drizzled/error.h>
19
#include <drizzled/unireg.h>
20
#include <drizzled/plugin/storage_engine.h>
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/session/cache.h"
30
#include "drizzled/drizzled.h"
32
#include <boost/thread/thread.hpp>
33
#include <boost/filesystem.hpp>
39
20
static bool kill_in_progress= false;
40
void signal_hand(void);
21
static bool volatile signal_thread_in_use= false;
44
22
extern int cleanup_done;
45
extern bool volatile abort_loop;
46
extern bool volatile shutdown_in_progress;
47
extern boost::filesystem::path pid_file;
48
25
/* Prototypes -> all of these should be factored out into a propper shutdown */
49
extern void close_connections(void);
50
extern std::bitset<12> test_flags;
53
using namespace drizzled;
26
void close_connections(void);
27
extern "C" void unireg_end(void);
28
extern "C" void unireg_abort(int exit_code);
29
bool reload_cache(Session *session, ulong options, TableList *tables, bool *write_to_binlog);
66
40
or stop, we just want to kill the server.
69
static void kill_server(int sig)
43
static void *kill_server(void *sig_ptr)
45
int sig=(int) (long) sig_ptr; // This is passed a int
71
46
// if there is a signal during the kill in progress, ignore the other
72
47
if (kill_in_progress) // Safety
74
49
kill_in_progress=true;
75
50
abort_loop=1; // This should be set
76
51
if (sig != 0) // 0 is not a valid signal number
77
ignore_signal(sig); /* purify inspected */
52
my_sigset(sig, SIG_IGN); /* purify inspected */
78
53
if (sig == SIGTERM || sig == 0)
79
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
54
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),my_progname);
81
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
56
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),my_progname,sig); /* purecov: inspected */
82
58
close_connections();
59
if (sig != SIGTERM && sig != 0)
60
unireg_abort(1); /* purecov: inspected */
64
/* purecov: begin deadcode */
105
93
(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());
95
snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
114
101
/** This threads handles all signals and alarms. */
104
pthread_handler_t signal_hand(void *)
119
internal::my_thread_init(); // Init new thread
120
boost::this_thread::at_thread_exit(&internal::my_thread_end);
108
my_thread_init(); // Init new thread
121
109
signal_thread_in_use= true;
123
if ((test_flags.test(TEST_SIGINT)))
111
if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
125
113
(void) sigemptyset(&set); // Setup up SIGINT for debug
126
114
(void) sigaddset(&set,SIGINT); // For debugging
129
117
(void) sigemptyset(&set); // Setup up SIGINT for debug
130
118
#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";
119
(void) sigaddset(&set,SIGQUIT);
120
(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";
122
(void) sigaddset(&set,SIGTERM);
123
(void) sigaddset(&set,SIGTSTP);
149
125
/* Save pid to this process (or thread on Linux) */
150
126
create_pid_file();
128
#ifdef HAVE_STACK_TRACE_ON_SEGV
131
sprintf(pstack_file_name,"drizzled-%lu-%%d-%%d.backtrace", (uint32_t)getpid());
132
pstack_install_segv_action(pstack_file_name);
134
#endif /* HAVE_STACK_TRACE_ON_SEGV */
153
137
signal to init that we are ready
154
138
This works by waiting for init to free mutex,
161
145
(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";
148
if (pthread_mutex_lock(&LOCK_thread_count) == 0)
149
(void) pthread_mutex_unlock(&LOCK_thread_count);
150
(void) pthread_cond_broadcast(&COND_thread_count);
152
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
175
155
int error; // Used when debugging
177
156
if (shutdown_in_progress && !abort_loop)
184
while ((error= sigwait(&set, &sig)) == EINTR) ;
162
while ((error= sigwait(&set,&sig)) == EINTR) ;
187
163
if (cleanup_done)
189
166
signal_thread_in_use= false;
198
174
/* switch to the old log message processing */
201
177
abort_loop=1; // mark abort for threads
202
kill_server(sig); // MIT THREAD has a alarm thread
178
kill_server((void*) sig); // MIT THREAD has a alarm thread
209
drizzled::plugin::StorageEngine::flushLogs(NULL);
185
reload_cache((Session*) 0, (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST ),
186
(TableList*) 0, ¬_used); // Flush logs
190
break; /* purecov: tested */
196
static int init(void *)
199
pthread_attr_t thr_attr;
200
size_t my_thread_stack_size= 65536;
202
(void) pthread_attr_init(&thr_attr);
203
pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
204
(void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
206
struct sched_param tmp_sched_param;
208
memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
209
tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
210
(void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
212
#if defined(__ia64__) || defined(__ia64)
214
Peculiar things with ia64 platforms - it seems we only have half the
215
stack size in reality, so we have to double it here
217
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
219
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
222
(void) pthread_mutex_lock(&LOCK_thread_count);
223
if ((error=pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
225
errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create interrupt-thread (error %d, errno: %d)"),
229
(void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
230
pthread_mutex_unlock(&LOCK_thread_count);
232
(void) pthread_attr_destroy(&thr_attr);
238
This is mainly needed when running with purify, but it's still nice to
239
know that all child threads have died when drizzled exits.
241
static int deinit(void *)
245
Wait up to 10 seconds for signal thread to die. We use this mainly to
246
avoid getting warnings that my_thread_end has not been called
248
for (i= 0 ; i < 100 && signal_thread_in_use; i++)
250
if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
218
class SignalHandler :
219
public drizzled::plugin::Daemon
221
SignalHandler(const SignalHandler &);
222
SignalHandler& operator=(const SignalHandler &);
223
boost::thread thread;
227
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);
237
This is mainly needed when running with purify, but it's still nice to
238
know that all child threads have died when drizzled exits.
243
Wait up to 100000 micro-seconds for signal thread to die. We use this mainly to
244
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--)
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";
267
boost::posix_time::milliseconds duration(100);
268
completed= thread.timed_join(duration);
274
static int init(drizzled::module::Context& context)
276
context.add(new SignalHandler);
252
usleep(100); // Give it time to die
282
static drizzle_sys_var* system_variables[]= {
258
static struct st_mysql_sys_var* system_variables[]= {
286
DRIZZLE_DECLARE_PLUGIN
262
drizzle_declare_plugin(signal_handler)
264
DRIZZLE_DAEMON_PLUGIN,
289
265
"signal_handler",
292
268
"Default Signal Handler",
293
269
PLUGIN_LICENSE_GPL,
294
270
init, /* Plugin Init */
271
deinit, /* Plugin Deinit */
272
NULL, /* status variables */
295
273
system_variables, /* system variables */
296
274
NULL /* config options */
298
DRIZZLE_DECLARE_PLUGIN_END;
276
drizzle_declare_plugin_end;