1
/* Copyright (C) 2006 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
#include <drizzled/server_includes.h>
17
#include <drizzled/gettext.h>
18
#include <drizzled/error.h>
20
static bool kill_in_progress= false;
21
static bool volatile signal_thread_in_use= false;
22
extern int cleanup_done;
25
/* Prototypes -> all of these should be factored out into a propper shutdown */
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);
33
Force server down. Kill all connections and threads and exit.
35
@param sig_ptr Signal number that caused kill_server to be called.
38
A signal number of 0 mean that the function was not called
39
from a signal handler and there is thus no signal to block
40
or stop, we just want to kill the server.
43
static void *kill_server(void *sig_ptr)
45
int sig=(int) (long) sig_ptr; // This is passed a int
46
// if there is a signal during the kill in progress, ignore the other
47
if (kill_in_progress) // Safety
49
kill_in_progress=true;
50
abort_loop=1; // This should be set
51
if (sig != 0) // 0 is not a valid signal number
52
my_sigset(sig, SIG_IGN); /* purify inspected */
53
if (sig == SIGTERM || sig == 0)
54
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),my_progname);
56
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),my_progname,sig); /* purecov: inspected */
59
if (sig != SIGTERM && sig != 0)
60
unireg_abort(1); /* purecov: inspected */
64
/* purecov: begin deadcode */
74
Create file to store pid number.
76
static void create_pid_file()
81
assert(pidfile_name[0]);
82
if ((file = open(pidfile_name, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU|S_IRGRP|S_IROTH)) > 0)
86
length= snprintf(buff, 1024, "%ld\n", (long) getpid());
88
if ((write(file, buff, length)) == length)
90
if (close(file) != -1)
93
(void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
95
snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
101
/** This threads handles all signals and alarms. */
104
pthread_handler_t signal_hand(void *)
108
my_thread_init(); // Init new thread
109
signal_thread_in_use= true;
111
if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
113
(void) sigemptyset(&set); // Setup up SIGINT for debug
114
(void) sigaddset(&set,SIGINT); // For debugging
115
(void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
117
(void) sigemptyset(&set); // Setup up SIGINT for debug
118
#ifndef IGNORE_SIGHUP_SIGQUIT
119
(void) sigaddset(&set,SIGQUIT);
120
(void) sigaddset(&set,SIGHUP);
122
(void) sigaddset(&set,SIGTERM);
123
(void) sigaddset(&set,SIGTSTP);
125
/* Save pid to this process (or thread on Linux) */
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 */
137
signal to init that we are ready
138
This works by waiting for init to free mutex,
139
after which we signal it that we are ready.
140
At this pointer there is no other threads running, so there
141
should not be any other pthread_cond_signal() calls.
143
We call lock/unlock to out wait any thread/session which is
144
dieing. Since only comes from this code, this should be safe.
145
(Asked MontyW over the phone about this.) -Brian
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);
155
int error; // Used when debugging
156
if (shutdown_in_progress && !abort_loop)
162
while ((error= sigwait(&set,&sig)) == EINTR) ;
166
signal_thread_in_use= false;
174
/* switch to the old log message processing */
177
abort_loop=1; // mark abort for threads
178
kill_server((void*) sig); // MIT THREAD has a alarm thread
185
reload_cache((Session*) 0,
186
(REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
188
(TableList*) 0, ¬_used); // Flush logs
192
break; /* purecov: tested */
198
static int init(void *)
201
pthread_attr_t thr_attr;
202
size_t my_thread_stack_size= 65536;
204
(void) pthread_attr_init(&thr_attr);
205
pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
206
(void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
208
struct sched_param tmp_sched_param;
210
memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
211
tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
212
(void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
214
#if defined(__ia64__) || defined(__ia64)
216
Peculiar things with ia64 platforms - it seems we only have half the
217
stack size in reality, so we have to double it here
219
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
221
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
224
(void) pthread_mutex_lock(&LOCK_thread_count);
225
if ((error=pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
227
errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create interrupt-thread (error %d, errno: %d)"),
231
(void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
232
pthread_mutex_unlock(&LOCK_thread_count);
234
(void) pthread_attr_destroy(&thr_attr);
240
This is mainly needed when running with purify, but it's still nice to
241
know that all child threads have died when drizzled exits.
243
static int deinit(void *)
247
Wait up to 10 seconds for signal thread to die. We use this mainly to
248
avoid getting warnings that my_thread_end has not been called
250
for (i= 0 ; i < 100 && signal_thread_in_use; i++)
252
if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
254
usleep(100); // Give it time to die
260
static struct st_mysql_sys_var* system_variables[]= {
264
drizzle_declare_plugin(signal_handler)
266
DRIZZLE_DAEMON_PLUGIN,
270
"Default Signal Handler",
272
init, /* Plugin Init */
273
deinit, /* Plugin Deinit */
274
NULL, /* status variables */
275
system_variables, /* system variables */
276
NULL /* config options */
278
drizzle_declare_plugin_end;