2
Copyright (C) 2011 Brian Aker
3
Copyright (C) 2006 MySQL AB
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
20
#include <drizzled/gettext.h>
21
#include <drizzled/error.h>
22
#include <drizzled/unireg.h>
23
#include <drizzled/plugin/storage_engine.h>
24
#include "drizzled/pthread_globals.h"
25
#include "drizzled/internal/my_pthread.h"
26
#include "drizzled/internal/my_sys.h"
27
#include "drizzled/plugin/daemon.h"
28
#include "drizzled/signal_handler.h"
30
#include <drizzled/session.h>
31
#include <drizzled/session/cache.h>
33
#include "drizzled/debug.h"
35
#include "drizzled/drizzled.h"
37
#include <drizzled/refresh_version.h>
39
#include <boost/thread/thread.hpp>
40
#include <boost/filesystem.hpp>
46
static bool kill_in_progress= false;
47
void signal_hand(void);
51
extern int cleanup_done;
52
extern bool volatile abort_loop;
53
extern bool volatile shutdown_in_progress;
54
extern boost::filesystem::path pid_file;
55
/* Prototypes -> all of these should be factored out into a propper shutdown */
56
extern void close_connections(void);
59
using namespace drizzled;
65
Force server down. Kill all connections and threads and exit.
67
@param sig_ptr Signal number that caused kill_server to be called.
70
A signal number of 0 mean that the function was not called
71
from a signal handler and there is thus no signal to block
72
or stop, we just want to kill the server.
75
static void kill_server(int sig)
77
// if there is a signal during the kill in progress, ignore the other
78
if (kill_in_progress) // Safety
80
kill_in_progress=true;
81
abort_loop=1; // This should be set
82
if (sig != 0) // 0 is not a valid signal number
83
ignore_signal(sig); /* purify inspected */
84
if (sig == SIGTERM || sig == 0)
85
errmsg_printf(error::INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
87
errmsg_printf(error::ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
94
Create file to store pid number.
96
static void create_pid_file()
101
if ((file = open(pid_file.file_string().c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU|S_IRGRP|S_IROTH)) > 0)
105
length= snprintf(buff, 1024, "%ld\n", (long) getpid());
107
if ((write(file, buff, length)) == length)
109
if (close(file) != -1)
112
(void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
114
memset(buff, 0, sizeof(buff));
115
snprintf(buff, sizeof(buff)-1, "Can't start server: can't create PID file (%s)", pid_file.file_string().c_str());
121
/** This threads handles all signals and alarms. */
126
internal::my_thread_init(); // Init new thread
127
boost::this_thread::at_thread_exit(&internal::my_thread_end);
128
signal_thread_in_use= true;
130
if ((drizzled::getDebug().test(drizzled::debug::ALLOW_SIGINT)))
132
(void) sigemptyset(&set); // Setup up SIGINT for debug
133
(void) sigaddset(&set,SIGINT); // For debugging
134
(void) pthread_sigmask(SIG_UNBLOCK, &set, NULL);
136
(void) sigemptyset(&set); // Setup up SIGINT for debug
137
#ifndef IGNORE_SIGHUP_SIGQUIT
138
if (sigaddset(&set,SIGQUIT))
140
std::cerr << "failed setting sigaddset() with SIGQUIT\n";
142
if (sigaddset(&set,SIGHUP))
144
std::cerr << "failed setting sigaddset() with SIGHUP\n";
147
if (sigaddset(&set,SIGTERM))
149
std::cerr << "failed setting sigaddset() with SIGTERM\n";
151
if (sigaddset(&set,SIGTSTP))
153
std::cerr << "failed setting sigaddset() with SIGTSTP\n";
156
/* Save pid to this process (or thread on Linux) */
160
signal to init that we are ready
161
This works by waiting for init to free mutex,
162
after which we signal it that we are ready.
163
At this pointer there is no other threads running, so there
164
should not be any other pthread_cond_signal() calls.
166
We call lock/unlock to out wait any thread/session which is
167
dieing. Since only comes from this code, this should be safe.
168
(Asked MontyW over the phone about this.) -Brian
171
session::Cache::singleton().mutex().lock();
172
session::Cache::singleton().mutex().unlock();
173
COND_thread_count.notify_all();
175
if (pthread_sigmask(SIG_BLOCK, &set, NULL))
177
std::cerr << "Failed to set pthread_sigmask() in signal handler\n";
182
int error; // Used when debugging
184
if (shutdown_in_progress && !abort_loop)
191
while ((error= sigwait(&set, &sig)) == EINTR) ;
196
signal_thread_in_use= false;
205
/* switch to the old log message processing */
208
abort_loop=1; // mark abort for threads
209
kill_server(sig); // MIT THREAD has a alarm thread
216
drizzled::plugin::StorageEngine::flushLogs(NULL);
225
class SignalHandler :
226
public drizzled::plugin::Daemon
228
SignalHandler(const SignalHandler &);
229
SignalHandler& operator=(const SignalHandler &);
230
boost::thread thread;
234
drizzled::plugin::Daemon("Signal Handler")
236
// @todo fix spurious wakeup issue
237
boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
238
thread= boost::thread(signal_hand);
239
signal_thread= thread.native_handle();
240
COND_thread_count.wait(scopedLock);
244
This is mainly needed when running with purify, but it's still nice to
245
know that all child threads have died when drizzled exits.
250
Wait up to 100000 micro-seconds for signal thread to die. We use this mainly to
251
avoid getting warnings that internal::my_thread_end has not been called
253
bool completed= false;
255
* We send SIGTERM and then do a timed join. If that fails we will on
256
* the last pthread_kill() call SIGTSTP. OSX (and FreeBSD) seem to
257
* prefer this. -Brian
259
uint32_t count= 2; // How many times to try join and see if the caller died.
260
while (not completed and count--)
263
int signal= count == 1 ? SIGTSTP : SIGTERM;
265
if ((error= pthread_kill(thread.native_handle(), signal)))
267
char buffer[1024]; // No reason for number;
268
strerror_r(error, buffer, sizeof(buffer));
269
std::cerr << "pthread_kill() error on shutdown of signal thread (" << buffer << ")\n";
274
boost::posix_time::milliseconds duration(100);
275
completed= thread.timed_join(duration);
281
static int init(drizzled::module::Context& context)
283
context.add(new SignalHandler);
289
DRIZZLE_DECLARE_PLUGIN
295
"Default Signal Handler",
297
init, /* Plugin Init */
299
NULL /* config options */
301
DRIZZLE_DECLARE_PLUGIN_END;