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, (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST ),
186
(TableList*) 0, ¬_used); // Flush logs
190
break; /* purecov: tested */
196
static int init(PluginRegistry&)
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(PluginRegistry&)
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)
252
usleep(100); // Give it time to die
258
static struct st_mysql_sys_var* system_variables[]= {
262
drizzle_declare_plugin(signal_handler)
267
"Default Signal Handler",
269
init, /* Plugin Init */
270
deinit, /* Plugin Deinit */
271
NULL, /* status variables */
272
system_variables, /* system variables */
273
NULL /* config options */
275
drizzle_declare_plugin_end;