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;
55
26
/* Prototypes -> all of these should be factored out into a propper shutdown */
56
extern void close_connections(void);
59
using namespace drizzled;
27
void close_connections(void);
28
bool reload_cache(Session *session, ulong options, TableList *tables);
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); /* purecov: inspected */
89
57
close_connections();
58
if (sig != SIGTERM && sig != 0)
59
unireg_abort(1); /* purecov: inspected */
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. */
95
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);
99
my_thread_init(); // Init new thread
128
100
signal_thread_in_use= true;
130
if ((drizzled::getDebug().test(drizzled::debug::ALLOW_SIGINT)))
102
if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
132
104
(void) sigemptyset(&set); // Setup up SIGINT for debug
133
105
(void) sigaddset(&set,SIGINT); // For debugging
134
(void) pthread_sigmask(SIG_UNBLOCK, &set, NULL);
106
(void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
136
108
(void) sigemptyset(&set); // Setup up SIGINT for debug
137
109
#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";
110
(void) sigaddset(&set,SIGQUIT);
111
(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";
113
(void) sigaddset(&set,SIGTERM);
114
(void) sigaddset(&set,SIGTSTP);
156
116
/* Save pid to this process (or thread on Linux) */
157
117
create_pid_file();
119
#ifdef HAVE_STACK_TRACE_ON_SEGV
122
sprintf(pstack_file_name,"drizzled-%lu-%%d-%%d.backtrace", (uint32_t)getpid());
123
pstack_install_segv_action(pstack_file_name);
125
#endif /* HAVE_STACK_TRACE_ON_SEGV */
160
128
signal to init that we are ready
161
129
This works by waiting for init to free mutex,
168
136
(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";
139
if (pthread_mutex_lock(&LOCK_thread_count) == 0)
140
(void) pthread_mutex_unlock(&LOCK_thread_count);
141
(void) pthread_cond_broadcast(&COND_thread_count);
143
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
182
146
int error; // Used when debugging
184
147
if (shutdown_in_progress && !abort_loop)
191
while ((error= sigwait(&set, &sig)) == EINTR) ;
153
while ((error= sigwait(&set,&sig)) == EINTR) ;
194
154
if (cleanup_done)
196
157
signal_thread_in_use= false;
205
165
/* switch to the old log message processing */
208
168
abort_loop=1; // mark abort for threads
209
kill_server(sig); // MIT THREAD has a alarm thread
169
kill_server((void*) sig); // MIT THREAD has a alarm thread
216
drizzled::plugin::StorageEngine::flushLogs(NULL);
174
reload_cache(NULL, (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST ), NULL); // Flush logs
177
break; /* purecov: tested */
183
static int init(PluginRegistry&)
186
pthread_attr_t thr_attr;
187
size_t my_thread_stack_size= 65536;
189
(void) pthread_attr_init(&thr_attr);
190
pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
191
(void) pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
193
struct sched_param tmp_sched_param;
195
memset(&tmp_sched_param, 0, sizeof(tmp_sched_param));
196
tmp_sched_param.sched_priority= INTERRUPT_PRIOR;
197
(void)pthread_attr_setschedparam(&thr_attr, &tmp_sched_param);
199
#if defined(__ia64__) || defined(__ia64)
201
Peculiar things with ia64 platforms - it seems we only have half the
202
stack size in reality, so we have to double it here
204
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size*2);
206
pthread_attr_setstacksize(&thr_attr, my_thread_stack_size);
209
(void) pthread_mutex_lock(&LOCK_thread_count);
210
if ((error=pthread_create(&signal_thread, &thr_attr, signal_hand, 0)))
212
errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create interrupt-thread (error %d, errno: %d)"),
216
(void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
217
pthread_mutex_unlock(&LOCK_thread_count);
219
(void) pthread_attr_destroy(&thr_attr);
225
This is mainly needed when running with purify, but it's still nice to
226
know that all child threads have died when drizzled exits.
228
static int deinit(PluginRegistry&)
232
Wait up to 10 seconds for signal thread to die. We use this mainly to
233
avoid getting warnings that my_thread_end has not been called
235
for (i= 0 ; i < 100 && signal_thread_in_use; i++)
237
if (pthread_kill(signal_thread, SIGTERM) != ESRCH)
239
usleep(100); // Give it time to die
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);
245
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
249
drizzle_declare_plugin(signal_handler)
292
251
"signal_handler",
295
254
"Default Signal Handler",
296
255
PLUGIN_LICENSE_GPL,
297
256
init, /* Plugin Init */
257
deinit, /* Plugin Deinit */
258
NULL, /* status variables */
259
system_variables, /* system variables */
299
260
NULL /* config options */
301
DRIZZLE_DECLARE_PLUGIN_END;
262
drizzle_declare_plugin_end;