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 */
17
#include <drizzled/gettext.h>
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/drizzled.h"
30
#include <boost/thread/thread.hpp>
36
static bool kill_in_progress= false;
37
void signal_hand(void);
41
extern int cleanup_done;
42
extern bool volatile abort_loop;
43
extern bool volatile shutdown_in_progress;
44
extern char pidfile_name[FN_REFLEN];
45
/* Prototypes -> all of these should be factored out into a propper shutdown */
46
extern void close_connections(void);
47
extern std::bitset<12> test_flags;
50
using namespace drizzled;
55
Force server down. Kill all connections and threads and exit.
57
@param sig_ptr Signal number that caused kill_server to be called.
60
A signal number of 0 mean that the function was not called
61
from a signal handler and there is thus no signal to block
62
or stop, we just want to kill the server.
65
static void kill_server(void *sig_ptr)
67
int sig=(int) (long) sig_ptr; // This is passed a int
68
// if there is a signal during the kill in progress, ignore the other
69
if (kill_in_progress) // Safety
71
kill_in_progress=true;
72
abort_loop=1; // This should be set
73
if (sig != 0) // 0 is not a valid signal number
74
ignore_signal(sig); /* purify inspected */
75
if (sig == SIGTERM || sig == 0)
76
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
78
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
84
Create file to store pid number.
86
static void create_pid_file()
91
assert(pidfile_name[0]);
92
if ((file = open(pidfile_name, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU|S_IRGRP|S_IROTH)) > 0)
96
length= snprintf(buff, 1024, "%ld\n", (long) getpid());
98
if ((write(file, buff, length)) == length)
100
if (close(file) != -1)
103
(void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
105
snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
111
/** This threads handles all signals and alarms. */
116
internal::my_thread_init(); // Init new thread
117
boost::this_thread::at_thread_exit(&internal::my_thread_end);
118
signal_thread_in_use= true;
120
if ((test_flags.test(TEST_SIGINT)))
122
(void) sigemptyset(&set); // Setup up SIGINT for debug
123
(void) sigaddset(&set,SIGINT); // For debugging
124
(void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
126
(void) sigemptyset(&set); // Setup up SIGINT for debug
127
#ifndef IGNORE_SIGHUP_SIGQUIT
128
if (sigaddset(&set,SIGQUIT))
130
std::cerr << "failed setting sigaddset() with SIGQUIT\n";
132
if (sigaddset(&set,SIGHUP))
134
std::cerr << "failed setting sigaddset() with SIGHUP\n";
137
if (sigaddset(&set,SIGTERM))
139
std::cerr << "failed setting sigaddset() with SIGTERM\n";
141
if (sigaddset(&set,SIGTSTP))
143
std::cerr << "failed setting sigaddset() with SIGTSTP\n";
146
/* Save pid to this process (or thread on Linux) */
150
signal to init that we are ready
151
This works by waiting for init to free mutex,
152
after which we signal it that we are ready.
153
At this pointer there is no other threads running, so there
154
should not be any other pthread_cond_signal() calls.
156
We call lock/unlock to out wait any thread/session which is
157
dieing. Since only comes from this code, this should be safe.
158
(Asked MontyW over the phone about this.) -Brian
161
LOCK_thread_count.lock();
162
LOCK_thread_count.unlock();
163
COND_thread_count.notify_all();
165
if (pthread_sigmask(SIG_BLOCK, &set, NULL))
167
std::cerr << "Failed to set pthread_sigmask() in signal handler\n";
172
int error; // Used when debugging
174
if (shutdown_in_progress && !abort_loop)
181
while ((error= sigwait(&set, &sig)) == EINTR) ;
186
signal_thread_in_use= false;
195
/* switch to the old log message processing */
198
abort_loop=1; // mark abort for threads
199
kill_server((void*) sig); // MIT THREAD has a alarm thread
206
drizzled::plugin::StorageEngine::flushLogs(NULL);
215
class SignalHandler :
216
public drizzled::plugin::Daemon
218
SignalHandler(const SignalHandler &);
219
SignalHandler& operator=(const SignalHandler &);
220
boost::thread thread;
224
drizzled::plugin::Daemon("Signal Handler")
226
// @todo fix spurious wakeup issue
227
boost::mutex::scoped_lock scopedLock(LOCK_thread_count);
228
thread= boost::thread(signal_hand);
229
signal_thread= thread.native_handle();
230
COND_thread_count.wait(scopedLock);
234
This is mainly needed when running with purify, but it's still nice to
235
know that all child threads have died when drizzled exits.
240
Wait up to 100000 micro-seconds for signal thread to die. We use this mainly to
241
avoid getting warnings that internal::my_thread_end has not been called
243
bool completed= false;
245
* We send SIGTERM and then do a timed join. If that fails we will on
246
* the last pthread_kill() call SIGTSTP. OSX (and FreeBSD) seem to
247
* prefer this. -Brian
249
uint32_t count= 2; // How many times to try join and see if the caller died.
250
while (not completed and count--)
253
int signal= count == 1 ? SIGTSTP : SIGTERM;
255
if ((error= pthread_kill(thread.native_handle(), signal)))
257
char buffer[1024]; // No reason for number;
258
strerror_r(error, buffer, sizeof(buffer));
259
std::cerr << "pthread_kill() error on shutdown of signal thread (" << buffer << ")\n";
264
boost::posix_time::milliseconds duration(100);
265
completed= thread.timed_join(duration);
271
static int init(drizzled::module::Context& context)
273
context.add(new SignalHandler);
279
static drizzle_sys_var* system_variables[]= {
283
DRIZZLE_DECLARE_PLUGIN
289
"Default Signal Handler",
291
init, /* Plugin Init */
292
system_variables, /* system variables */
293
NULL /* config options */
295
DRIZZLE_DECLARE_PLUGIN_END;