15
13
along with this program; if not, write to the Free Software
16
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
#include <drizzled/server_includes.h>
20
17
#include <drizzled/gettext.h>
21
18
#include <drizzled/error.h>
22
19
#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
21
static bool kill_in_progress= false;
47
void signal_hand(void);
22
static bool volatile signal_thread_in_use= false;
51
23
extern int cleanup_done;
52
extern bool volatile abort_loop;
53
extern bool volatile shutdown_in_progress;
54
extern boost::filesystem::path pid_file;
24
extern "C" pthread_handler_t signal_hand(void *);
55
27
/* Prototypes -> all of these should be factored out into a propper shutdown */
56
28
extern void close_connections(void);
59
using namespace drizzled;
72
39
or stop, we just want to kill the server.
75
static void kill_server(int sig)
42
static void kill_server(void *sig_ptr)
44
int sig=(int) (long) sig_ptr; // This is passed a int
77
45
// if there is a signal during the kill in progress, ignore the other
78
46
if (kill_in_progress) // Safety
80
48
kill_in_progress=true;
81
49
abort_loop=1; // This should be set
82
50
if (sig != 0) // 0 is not a valid signal number
83
ignore_signal(sig); /* purify inspected */
51
my_sigset(sig, SIG_IGN); /* purify inspected */
84
52
if (sig == SIGTERM || sig == 0)
85
errmsg_printf(error::INFO, _(ER(ER_NORMAL_SHUTDOWN)),internal::my_progname);
53
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_NORMAL_SHUTDOWN)),my_progname);
87
errmsg_printf(error::ERROR, _(ER(ER_GOT_SIGNAL)),internal::my_progname,sig);
55
errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_GOT_SIGNAL)),my_progname,sig);
89
57
close_connections();
58
if (sig != SIGTERM && sig != 0)
112
84
(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());
86
snprintf(buff, 1024, "Can't start server: can't create PID file (%s)", pidfile_name);
121
92
/** This threads handles all signals and alarms. */
93
pthread_handler_t signal_hand(void *)
126
internal::my_thread_init(); // Init new thread
127
boost::this_thread::at_thread_exit(&internal::my_thread_end);
97
my_thread_init(); // Init new thread
128
98
signal_thread_in_use= true;
130
if ((drizzled::getDebug().test(drizzled::debug::ALLOW_SIGINT)))
100
if (thd_lib_detected != THD_LIB_LT &&
101
(test_flags.test(TEST_SIGINT)))
132
103
(void) sigemptyset(&set); // Setup up SIGINT for debug
133
104
(void) sigaddset(&set,SIGINT); // For debugging
134
(void) pthread_sigmask(SIG_UNBLOCK, &set, NULL);
105
(void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
136
107
(void) sigemptyset(&set); // Setup up SIGINT for debug
137
108
#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";
109
(void) sigaddset(&set,SIGQUIT);
110
(void) sigaddset(&set,SIGHUP);
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";
112
(void) sigaddset(&set,SIGTERM);
113
(void) sigaddset(&set,SIGTSTP);
156
115
/* Save pid to this process (or thread on Linux) */
157
116
create_pid_file();
118
#ifdef HAVE_STACK_TRACE_ON_SEGV
121
sprintf(pstack_file_name,"drizzled-%lu-%%d-%%d.backtrace", (uint32_t)getpid());
122
pstack_install_segv_action(pstack_file_name);
124
#endif /* HAVE_STACK_TRACE_ON_SEGV */
160
127
signal to init that we are ready
161
128
This works by waiting for init to free mutex,
168
135
(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";
138
if (pthread_mutex_lock(&LOCK_thread_count) == 0)
139
(void) pthread_mutex_unlock(&LOCK_thread_count);
140
(void) pthread_cond_broadcast(&COND_thread_count);
142
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
182
145
int error; // Used when debugging
184
146
if (shutdown_in_progress && !abort_loop)
191
while ((error= sigwait(&set, &sig)) == EINTR) ;
152
while ((error= sigwait(&set,&sig)) == EINTR) ;
194
153
if (cleanup_done)
196
156
signal_thread_in_use= false;
205
164
/* switch to the old log message processing */
208
167
abort_loop=1; // mark abort for threads
209
kill_server(sig); // MIT THREAD has a alarm thread
168
kill_server((void*) sig); // MIT THREAD has a alarm thread
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);
185
static int init(drizzled::plugin::Registry&)
188
pthread_attr_t thr_attr;
189
size_t my_thread_stack_size= 65536;
191
(void) pthread_attr_init(&thr_attr);
192
pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
193
(void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
195
struct sched_param tmp_sched_param;
197
memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
198
tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
199
(void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
201
#if defined(__ia64__) || defined(__ia64)
203
Peculiar things with ia64 platforms - it seems we only have half the
204
stack size in reality, so we have to double it here
206
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
208
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
211
(void) pthread_mutex_lock(&LOCK_thread_count);
212
if ((error=pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
214
errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create interrupt-thread (error %d, errno: %d)"),
218
(void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
219
pthread_mutex_unlock(&LOCK_thread_count);
221
(void) pthread_attr_destroy(&thr_attr);
227
This is mainly needed when running with purify, but it's still nice to
228
know that all child threads have died when drizzled exits.
230
static int deinit(drizzled::plugin::Registry&)
234
Wait up to 10 seconds for signal thread to die. We use this mainly to
235
avoid getting warnings that my_thread_end has not been called
237
for (i= 0 ; i < 100 && signal_thread_in_use; i++)
239
if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
241
usleep(100); // Give it time to die
247
static struct st_mysql_sys_var* system_variables[]= {
281
static int init(drizzled::module::Context& context)
283
context.add(new SignalHandler);
289
DRIZZLE_DECLARE_PLUGIN
251
drizzle_declare_plugin(signal_handler)
292
253
"signal_handler",
295
256
"Default Signal Handler",
296
257
PLUGIN_LICENSE_GPL,
297
258
init, /* Plugin Init */
259
deinit, /* Plugin Deinit */
260
NULL, /* status variables */
261
system_variables, /* system variables */
299
262
NULL /* config options */
301
DRIZZLE_DECLARE_PLUGIN_END;
264
drizzle_declare_plugin_end;